blob: d2c0e6fdc783986657d6f4dde5302f38e582997c [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;
developer5884e982022-10-06 10:52:50 +0800449 int i = 0;
developerc707e972022-09-13 15:38:02 +0800450 wifi_band band = band_invalid;
451
452 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5884e982022-10-06 10:52:50 +0800453 while(i < 10){
454 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
455 _syscmd(cmd, buf, sizeof(buf));
456 freq = strtol(buf, NULL, 10);
457 if (freq > 2401 && freq < 2495)
458 band = band_2_4;
459 else if (freq > 5160 && freq < 5915)
460 band = band_5;
461 else if (freq > 5955 && freq < 7125)
462 band = band_6;
463
464 if(band != band_invalid)
465 break;
466
467 i++;
468 sleep(1);
469 }
developerc707e972022-09-13 15:38:02 +0800470
471 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
472 return band;
473}
474
developer06a01d92022-09-07 16:32:39 +0800475static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
476{
477 char cmd[MAX_CMD_SIZE]={'\0'};
478 char buf[MAX_BUF_SIZE]={'\0'};
479 int ret = 0;
480
481 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
482 ret = _syscmd(cmd, buf, sizeof(buf));
483 if ((ret != 0) && (strlen(buf) == 0))
484 return -1;
485 snprintf(output, output_size, "%s", buf);
486
487 return 0;
488}
489
490static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
491{
492 char cmd[MAX_CMD_SIZE]={'\0'};
493 char buf[MAX_BUF_SIZE]={'\0'};
494
495 for(int i=0;i<item_count;i++)
496 {
497 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
498 if (strlen(buf) == 0) //Insert
499 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
500 else //Update
501 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developer5884e982022-10-06 10:52:50 +0800502
developer06a01d92022-09-07 16:32:39 +0800503 if(_syscmd(cmd, buf, sizeof(buf)))
504 return -1;
505 }
506
507 return 0;
508}
509
510static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
511{
developer1e5aa162022-09-13 16:06:24 +0800512 if (multiple_set == TRUE)
513 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800514 char cmd[MAX_CMD_SIZE]="", output[32]="";
515 FILE *fp;
516 int i;
517 //NOTE RELOAD should be done in ApplySSIDSettings
518
519 for(i=0; i<item_count; i++, list++)
520 {
521 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
522 if((fp = popen(cmd, "r"))==NULL)
523 {
524 perror("popen failed");
525 return -1;
526 }
527 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
528 {
529 pclose(fp);
530 perror("fgets failed");
531 return -1;
532 }
533 pclose(fp);
534 }
535 return 0;
536}
537
538static int wifi_reloadAp(int apIndex)
539{
developer1e5aa162022-09-13 16:06:24 +0800540 if (multiple_set == TRUE)
541 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800542 char cmd[MAX_CMD_SIZE]="";
543 char buf[MAX_BUF_SIZE]="";
544
545 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
546 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
547 return RETURN_ERR;
548
549 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
550 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
551 return RETURN_ERR;
552
553 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
554 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
555 return RETURN_ERR;
556
557 return RETURN_OK;
558}
559
560
561//For Getting Current Interface Name from corresponding hostapd configuration
562void GetInterfaceName(char *interface_name, char *conf_file)
563{
564 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
565 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
567}
568
569INT File_Reading(CHAR *file, char *Value)
570{
571 FILE *fp = NULL;
572 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
573 int count = 0;
574
575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
576 fp = popen(file,"r");
577 if(fp == NULL)
578 return RETURN_ERR;
579
580 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
581 {
582 for(count=0;buf[count]!='\n';count++)
583 copy_buf[count]=buf[count];
584 copy_buf[count]='\0';
585 }
586 strcpy(Value,copy_buf);
587 pclose(fp);
588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
589
590 return RETURN_OK;
591}
592
593void wifi_RestartHostapd_2G()
594{
595 int Public2GApIndex = 4;
596
597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
598 wifi_setApEnable(Public2GApIndex, FALSE);
599 wifi_setApEnable(Public2GApIndex, TRUE);
600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
601}
602
603void wifi_RestartHostapd_5G()
604{
605 int Public5GApIndex = 5;
606
607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
608 wifi_setApEnable(Public5GApIndex, FALSE);
609 wifi_setApEnable(Public5GApIndex, TRUE);
610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
611}
612
613void wifi_RestartPrivateWifi_2G()
614{
615 int PrivateApIndex = 0;
616
617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
618 wifi_setApEnable(PrivateApIndex, FALSE);
619 wifi_setApEnable(PrivateApIndex, TRUE);
620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
621}
622
623void wifi_RestartPrivateWifi_5G()
624{
625 int Private5GApIndex = 1;
626
627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
628 wifi_setApEnable(Private5GApIndex, FALSE);
629 wifi_setApEnable(Private5GApIndex, TRUE);
630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
631}
632
633static int writeBandWidth(int radioIndex,char *bw_value)
634{
635 char buf[MAX_BUF_SIZE];
636 char cmd[MAX_CMD_SIZE];
637
638 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
639 if(_syscmd(cmd, buf, sizeof(buf)))
640 {
641 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
642 _syscmd(cmd, buf, sizeof(buf));
643 return RETURN_OK;
644 }
645
646 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
647 _syscmd(cmd,buf,sizeof(buf));
648 return RETURN_OK;
649}
650
651static int readBandWidth(int radioIndex,char *bw_value)
652{
653 char buf[MAX_BUF_SIZE];
654 char cmd[MAX_CMD_SIZE];
655 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
656 _syscmd(cmd,buf,sizeof(buf));
657 if(NULL!=strstr(buf,"20MHz"))
658 {
659 strcpy(bw_value,"20MHz");
660 }
661 else if(NULL!=strstr(buf,"40MHz"))
662 {
663 strcpy(bw_value,"40MHz");
664 }
665 else if(NULL!=strstr(buf,"80MHz"))
666 {
667 strcpy(bw_value,"80MHz");
668 }
669 else
670 {
671 return RETURN_ERR;
672 }
673 return RETURN_OK;
674}
675
developer39a5efb2022-09-13 16:09:06 +0800676INT wifi_getMaxRadioNumber(INT *max_radio_num)
677{
678 char cmd[64] = {0};
679 char buf[4] = {0};
680
681 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
682
683 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
684 _syscmd(cmd, buf, sizeof(buf));
685 *max_radio_num = strtoul(buf, NULL, 10);
686
687 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
688
689 return RETURN_OK;
690}
691
developer5f222492022-09-13 15:21:52 +0800692// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800693INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
694{
developer5f222492022-09-13 15:21:52 +0800695 struct params params={'\0'};
696 char config_file[MAX_BUF_SIZE] = {0};
697 char buf[MAX_BUF_SIZE] = {'\0'};
698
699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
700 if (strlen (beaconRate) < 5)
701 return RETURN_ERR;
702 // Copy the numeric value
703 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
704 buf[strlen(beaconRate) - 4] = '\0';
705
706 params.name = "beacon_rate";
707 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
708 if (strncmp(buf, "5.5", 3) == 0) {
709 snprintf(buf, sizeof(buf), "55");
710 params.value = buf;
711 } else {
712 strcat(buf, "0");
713 params.value = buf;
714 }
715
716 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
717 wifi_hostapdWrite(config_file, &params, 1);
718 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
719 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
720
721 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800722}
723
724INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
725{
developer5f222492022-09-13 15:21:52 +0800726 char config_file[MAX_BUF_SIZE] = {'\0'};
727 char temp_output[MAX_BUF_SIZE] = {'\0'};
728 char buf[MAX_BUF_SIZE] = {'\0'};
729 float rate = 0;
730
731 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
732 if (NULL == beaconRate)
733 return RETURN_ERR;
734
735 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
736 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
737 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
738 if(strlen(buf) > 0) {
739 rate = atof(buf)/10;
740 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
741 } else {
742 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
743 }
744 strncpy(beaconRate, temp_output, sizeof(temp_output));
745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
746
747 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800748}
749
750INT wifi_setLED(INT radioIndex, BOOL enable)
751{
752 return 0;
753}
754INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
755{
756 return RETURN_OK;
757}
758/**********************************************************************************
759 *
760 * Wifi Subsystem level function prototypes
761 *
762**********************************************************************************/
763//---------------------------------------------------------------------------------------------------
764//Wifi system api
765//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
766INT wifi_getHalVersion(CHAR *output_string) //RDKB
767{
768 if(!output_string)
769 return RETURN_ERR;
770 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
771
772 return RETURN_OK;
773}
774
775
776/* wifi_factoryReset() function */
777/**
778* @description Clears internal variables to implement a factory reset of the Wi-Fi
779* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
780*
781* @param None
782*
783* @return The status of the operation.
784* @retval RETURN_OK if successful.
785* @retval RETURN_ERR if any error is detected
786*
787* @execution Synchronous
788* @sideeffect None
789*
790* @note This function must not suspend and must not invoke any blocking system
791* calls. It should probably just send a message to a driver event handler task.
792*
793*/
794INT wifi_factoryReset()
795{
796 char cmd[128];
797
798 /*delete running hostapd conf files*/
799 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
800 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
801 system(cmd);
802 system("systemctl restart hostapd.service");
803
804 return RETURN_OK;
805}
806
807/* wifi_factoryResetRadios() function */
808/**
809* @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.
810*
811* @param None
812* @return The status of the operation
813* @retval RETURN_OK if successful
814* @retval RETURN_ERR if any error is detected
815*
816* @execution Synchronous
817*
818* @sideeffect None
819*
820* @note This function must not suspend and must not invoke any blocking system
821* calls. It should probably just send a message to a driver event handler task.
822*
823*/
824INT wifi_factoryResetRadios()
825{
826 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
827 return RETURN_OK;
828
829 return RETURN_ERR;
830}
831
832
833/* wifi_factoryResetRadio() function */
834/**
835* @description Restore selected radio parameters without touching access point parameters
836*
837* @param radioIndex - Index of Wi-Fi Radio channel
838*
839* @return The status of the operation.
840* @retval RETURN_OK if successful.
841* @retval RETURN_ERR if any error is detected
842*
843* @execution Synchronous.
844* @sideeffect None.
845*
846* @note This function must not suspend and must not invoke any blocking system
847* calls. It should probably just send a message to a driver event handler task.
848*
849*/
850INT wifi_factoryResetRadio(int radioIndex) //RDKB
851{
developer5ff7f5f2022-09-13 15:12:16 +0800852 system("systemctl stop hostapd.service");
853
developer06a01d92022-09-07 16:32:39 +0800854 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
855 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800856 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800857 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800858 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800859 else
860 return RETURN_ERR;
861
developer5ff7f5f2022-09-13 15:12:16 +0800862 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800863 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
864 return RETURN_OK;
865}
866
867/* wifi_initRadio() function */
868/**
869* Description: This function call initializes the specified radio.
870* Implementation specifics may dictate the functionality since
871* different hardware implementations may have different initilization requirements.
872* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
873*
874* @return The status of the operation.
875* @retval RETURN_OK if successful.
876* @retval RETURN_ERR if any error is detected
877*
878* @execution Synchronous.
879* @sideeffect None.
880*
881* @note This function must not suspend and must not invoke any blocking system
882* calls. It should probably just send a message to a driver event handler task.
883*
884*/
885INT wifi_initRadio(INT radioIndex)
886{
887 //TODO: Initializes the wifi subsystem (for specified radio)
888 return RETURN_OK;
889}
890void macfilter_init()
891{
892 char count[4]={'\0'};
893 char buf[253]={'\0'};
894 char tmp[19]={'\0'};
895 int dev_count,block,mac_entry=0;
896 char res[4]={'\0'};
897 char acl_file_path[64] = {'\0'};
898 FILE *fp = NULL;
899 int index=0;
900 char iface[10]={'\0'};
901 char config_file[MAX_BUF_SIZE] = {0};
902
903
904 sprintf(acl_file_path,"/tmp/mac_filter.sh");
905
906 fp=fopen(acl_file_path,"w+");
907 sprintf(buf,"#!/bin/sh \n");
908 fprintf(fp,"%s\n",buf);
909
910 system("chmod 0777 /tmp/mac_filter.sh");
911
912 for(index=0;index<=1;index++)
913 {
914 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
915 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
916 sprintf(buf,"syscfg get %dcountfilter",index);
917 _syscmd(buf,count,sizeof(count));
918 mac_entry=atoi(count);
919
920 sprintf(buf,"syscfg get %dblockall",index);
921 _syscmd(buf,res,sizeof(res));
922 block = atoi(res);
923
924 //Allow only those macs mentioned in ACL
925 if(block==1)
926 {
927 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
928 fprintf(fp,"%s\n",buf);
929 for(dev_count=1;dev_count<=mac_entry;dev_count++)
930 {
931 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
932 _syscmd(buf,tmp,sizeof(tmp));
933 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
934 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
935 fprintf(fp,"%s\n",buf);
936 }
937 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
938 fprintf(fp,"%s\n",buf);
939 }
940
941 //Block all the macs mentioned in ACL
942 else if(block==2)
943 {
944 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
945 fprintf(fp,"%s\n",buf);
946
947 for(dev_count=1;dev_count<=mac_entry;dev_count++)
948 {
949 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
950 _syscmd(buf,tmp,sizeof(tmp));
951 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
952 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
953 fprintf(fp,"%s\n",buf);
954 }
955 }
956 }
957 fclose(fp);
958}
959
960// Initializes the wifi subsystem (all radios)
961INT wifi_init() //RDKB
962{
963 char interface[MAX_BUF_SIZE]={'\0'};
964 char bridge_name[MAX_BUF_SIZE]={'\0'};
965 INT len=0;
966
967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
968 //Not intitializing macfilter for Turris-Omnia Platform for now
969 //macfilter_init();
970
971 system("/usr/sbin/iw reg set US");
972 system("systemctl start hostapd.service");
973 sleep(2);//sleep to wait for hostapd to start
974
975 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
976
977 return RETURN_OK;
978}
979
980/* wifi_reset() function */
981/**
982* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
983* Implementation specifics may dictate what is actualy reset since
984* different hardware implementations may have different requirements.
985* Parameters : None
986*
987* @return The status of the operation.
988* @retval RETURN_OK if successful.
989* @retval RETURN_ERR if any error is detected
990*
991* @execution Synchronous.
992* @sideeffect None.
993*
994* @note This function must not suspend and must not invoke any blocking system
995* calls. It should probably just send a message to a driver event handler task.
996*
997*/
998INT wifi_reset()
999{
1000 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001001 system("systemctl stop hostapd.service");
1002 sleep(2);
1003 system("systemctl start hostapd.service");
1004 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001005 return RETURN_OK;
1006}
1007
1008/* wifi_down() function */
1009/**
1010* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1011* Implementation specifics may dictate some functionality since
1012* different hardware implementations may have different requirements.
1013*
1014* @param None
1015*
1016* @return The status of the operation
1017* @retval RETURN_OK if successful
1018* @retval RETURN_ERR if any error is detected
1019*
1020* @execution Synchronous
1021* @sideeffect None
1022*
1023* @note This function must not suspend and must not invoke any blocking system
1024* calls. It should probably just send a message to a driver event handler task.
1025*
1026*/
1027INT wifi_down()
1028{
1029 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001030 system("systemctl stop hostapd.service");
1031 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001032 return RETURN_OK;
1033}
1034
1035
1036/* wifi_createInitialConfigFiles() function */
1037/**
1038* @description This function creates wifi configuration files. The format
1039* and content of these files are implementation dependent. This function call is
1040* used to trigger this task if necessary. Some implementations may not need this
1041* function. If an implementation does not need to create config files the function call can
1042* do nothing and return RETURN_OK.
1043*
1044* @param None
1045*
1046* @return The status of the operation
1047* @retval RETURN_OK if successful
1048* @retval RETURN_ERR if any error is detected
1049*
1050* @execution Synchronous
1051* @sideeffect None
1052*
1053* @note This function must not suspend and must not invoke any blocking system
1054* calls. It should probably just send a message to a driver event handler task.
1055*
1056*/
1057INT wifi_createInitialConfigFiles()
1058{
1059 //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)
1060 return RETURN_OK;
1061}
1062
1063// outputs the country code to a max 64 character string
1064INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1065{
developer7543b3b2022-09-13 13:47:17 +08001066 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1067 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001068 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001069
1070 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1071 _syscmd(cmd, buf, sizeof(buf));
1072 if(strlen(buf) > 0)
1073 snprintf(output_string, 64, "%s", buf);
1074 else
1075 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001076
1077 return RETURN_OK;
1078}
1079
1080INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1081{
1082 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001083 char str[MAX_BUF_SIZE]={'\0'};
1084 char cmd[MAX_CMD_SIZE]={'\0'};
1085 struct params params;
1086 char config_file[MAX_BUF_SIZE] = {0};
1087
1088 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1089 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1090 return RETURN_ERR;
1091
1092 params.name = "country_code";
1093 params.value = CountryCode;
1094 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1095 int ret = wifi_hostapdWrite(config_file, &params, 1);
1096 if (ret) {
1097 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1098 ,__func__, ret);
1099 }
1100
1101 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1102 if (ret) {
1103 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1104 ,__func__, ret);
1105 }
1106 wifi_reloadAp(radioIndex);
1107 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1108
developer06a01d92022-09-07 16:32:39 +08001109 return RETURN_OK;
1110}
1111
developera748dcf2022-09-13 15:56:48 +08001112INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1113{
1114 char channel_util_file[64] = {0};
1115 char cmd[128] = {0};
1116 char buf[128] = {0};
1117 char line[128] = {0};
1118 char *param = NULL, *value = NULL;
1119 int read = 0;
1120 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1121 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1122 size_t len = 0;
1123 FILE *f = NULL;
1124
1125 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1126
1127 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1128 _syscmd(cmd, buf, sizeof(buf));
1129 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1130
1131 memset(cmd, 0, sizeof(cmd));
1132 memset(buf, 0, sizeof(buf));
1133 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1134 if ((f = popen(cmd, "r")) == NULL) {
1135 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1136 return RETURN_ERR;
1137 }
1138
1139 read = getline(&line, &len, f);
1140 while (read != -1) {
1141 param = strtok(line, ":\t");
1142 value = strtok(NULL, " ");
1143 if(strstr(param, "frequency") != NULL) {
1144 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1145 }
1146 if(strstr(param, "noise") != NULL) {
1147 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1148 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1149 }
1150 if(strstr(param, "channel active time") != NULL) {
1151 ActiveTime = strtol(value, NULL, 10);
1152 }
1153 if(strstr(param, "channel busy time") != NULL) {
1154 BusyTime = strtol(value, NULL, 10);
1155 }
1156 if(strstr(param, "channel transmit time") != NULL) {
1157 TransmitTime = strtol(value, NULL, 10);
1158 }
1159 read = getline(&line, &len, f);
1160 }
1161 pclose(f);
1162
1163 // The file should store the last active, busy and transmit time
1164 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1165 f = fopen(channel_util_file, "r");
1166 if (f != NULL) {
1167 read = getline(&line, &len, f);
1168 preActiveTime = strtol(line, NULL, 10);
1169 read = getline(&line, &len, f);
1170 preBusyTime = strtol(line, NULL, 10);
1171 read = getline(&line, &len, f);
1172 preTransmitTime = strtol(line, NULL, 10);
1173 fclose(f);
1174 }
1175
1176 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1177 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1178
1179 f = fopen(channel_util_file, "w");
1180 if (f != NULL) {
1181 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1182 fclose(f);
1183 }
1184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1185 return RETURN_OK;
1186}
1187
developer06a01d92022-09-07 16:32:39 +08001188/**********************************************************************************
1189 *
1190 * Wifi radio level function prototypes
1191 *
1192**********************************************************************************/
1193
1194//Get the total number of radios in this wifi subsystem
1195INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1196{
1197 if (NULL == output)
1198 return RETURN_ERR;
1199 *output = 2;
1200
1201 return RETURN_OK;
1202}
1203
1204//Get the total number of SSID entries in this wifi subsystem
1205INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1206{
1207 if (NULL == output)
1208 return RETURN_ERR;
1209 *output = MAX_APS;
1210
1211 return RETURN_OK;
1212}
1213
1214//Get the Radio enable config parameter
1215INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1216{
1217 char interface_path[MAX_CMD_SIZE] = {0};
1218 FILE *fp = NULL;
1219
1220 if (NULL == output_bool)
1221 return RETURN_ERR;
1222
1223 *output_bool = FALSE;
1224 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1225 return RETURN_ERR;
1226
1227 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1228 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001229 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001230 {
developercf48e482022-09-13 14:49:50 +08001231 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001232 }
1233 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001234 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1235 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1236 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001237
developercf48e482022-09-13 14:49:50 +08001238 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1239 *output_bool = TRUE;
1240 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001241 return RETURN_OK;
1242}
1243
1244INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1245{
1246 char cmd[MAX_CMD_SIZE] = {0};
1247 char buf[MAX_CMD_SIZE] = {0};
1248 int apIndex, ret;
1249 FILE *fp = NULL;
1250
1251 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1252 if(enable==FALSE)
1253 {
1254 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1255 {
1256 //Detaching %s%d from hostapd daemon
1257 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1258 _syscmd(cmd, buf, sizeof(buf));
1259 if(strncmp(buf, "OK", 2))
1260 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1261 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1262 _syscmd(cmd, buf, sizeof(buf));
1263 }
developer456aa3e2022-09-13 14:27:36 +08001264 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001265 _syscmd(cmd, buf, sizeof(buf));
1266 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001267 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001268 }
1269 else
1270 {
developer456aa3e2022-09-13 14:27:36 +08001271 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001272 _syscmd(cmd, buf, sizeof(buf));
1273 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001274 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001275 sleep(1);
1276 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1277 {
1278 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1279 fp = fopen(cmd, "r");
1280 if(!fp)
1281 {
1282 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1283 _syscmd(cmd, buf, sizeof(buf));
1284 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1285 _syscmd(cmd, buf, sizeof(buf));
1286 }
1287 if(fp)
1288 fclose(fp);
1289 }
1290 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1291 {
1292 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1293 ret = _syscmd(cmd, buf, sizeof(buf));
1294 if ( ret == RETURN_ERR)
1295 {
1296 fprintf(stderr, "VAP interface creation failed\n");
1297 continue;
1298 }
1299 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1300 _syscmd(cmd, buf, sizeof(buf));
1301 if(*buf == '1')
1302 {
1303 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1304 radioIndex, apIndex);
1305 _syscmd(cmd, buf, sizeof(buf));
1306 if(strncmp(buf, "OK", 2))
1307 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1308 }
1309 }
1310 }
1311
1312 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1313 return RETURN_OK;
1314}
1315
1316//Get the Radio enable status
1317INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1318{
1319 if (NULL == output_bool)
1320 return RETURN_ERR;
1321
1322 return wifi_getRadioEnable(radioIndex, output_bool);
1323}
1324
1325//Get the Radio Interface name from platform, eg "wlan0"
1326INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1327{
1328 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1329 return RETURN_ERR;
1330 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1331
1332 return RETURN_OK;
1333}
1334
1335//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1336//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.
1337INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1338{
developerbcc556a2022-09-22 20:02:45 +08001339 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1340 // For max bit rate, we should always choose the best MCS
1341 char mode[64] = {0};
1342 char channel_bandwidth_str[16] = {0};
1343 char *tmp = NULL;
1344 UINT mode_map = 0;
1345 UINT num_subcarrier = 0;
1346 UINT code_bits = 0;
1347 float code_rate = 0; // use max code rate
1348 int NSS = 0;
1349 UINT Symbol_duration = 0;
1350 UINT GI_duration = 0;
1351 wifi_band band = band_invalid;
1352 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1353 BOOL enable = FALSE;
1354 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001355
1356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1357 if (NULL == output_string)
1358 return RETURN_ERR;
1359
developerbcc556a2022-09-22 20:02:45 +08001360 wifi_getRadioEnable(radioIndex, &enable);
1361 if (enable == FALSE) {
1362 snprintf(output_string, 64, "0 Mb/s");
1363 return RETURN_OK;
1364 }
1365
1366 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1367 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1368 return RETURN_ERR;
1369 }
1370
1371 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1372 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1373 return RETURN_ERR;
1374 }
1375
1376 if (gi == wifi_guard_interval_3200)
1377 GI_duration = 32;
1378 else if (gi == wifi_guard_interval_1600)
1379 GI_duration = 16;
1380 else if (gi == wifi_guard_interval_800)
1381 GI_duration = 8;
1382 else // auto, 400
1383 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001384
developerbcc556a2022-09-22 20:02:45 +08001385 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1386 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1387 return RETURN_ERR;
1388 }
1389
1390 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1391 strcpy(channel_bandwidth_str, "160");
1392
1393 if (mode_map & WIFI_MODE_AX) {
1394 if (strstr(channel_bandwidth_str, "160") != NULL)
1395 num_subcarrier = 1960;
1396 else if (strstr(channel_bandwidth_str, "80") != NULL)
1397 num_subcarrier = 980;
1398 else if (strstr(channel_bandwidth_str, "40") != NULL)
1399 num_subcarrier = 468;
1400 else if (strstr(channel_bandwidth_str, "20") != NULL)
1401 num_subcarrier = 234;
1402 code_bits = 10;
1403 code_rate = (float)5/6;
1404 Symbol_duration = 128;
1405 } else if (mode_map & WIFI_MODE_AC) {
1406 if (strstr(channel_bandwidth_str, "160") != NULL)
1407 num_subcarrier = 468;
1408 else if (strstr(channel_bandwidth_str, "80") != NULL)
1409 num_subcarrier = 234;
1410 else if (strstr(channel_bandwidth_str, "40") != NULL)
1411 num_subcarrier = 108;
1412 else if (strstr(channel_bandwidth_str, "20") != NULL)
1413 num_subcarrier = 52;
1414 code_bits = 8;
1415 code_rate = (float)5/6;
1416 Symbol_duration = 32;
1417 } else if (mode_map & WIFI_MODE_N) {
1418 if (strstr(channel_bandwidth_str, "160") != NULL)
1419 num_subcarrier = 468;
1420 else if (strstr(channel_bandwidth_str, "80") != NULL)
1421 num_subcarrier = 234;
1422 else if (strstr(channel_bandwidth_str, "40") != NULL)
1423 num_subcarrier = 108;
1424 else if (strstr(channel_bandwidth_str, "20") != NULL)
1425 num_subcarrier = 52;
1426 code_bits = 6;
1427 code_rate = (float)3/4;
1428 Symbol_duration = 32;
1429 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1430 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1431 snprintf(output_string, 64, "65 Mb/s");
1432 return RETURN_OK;
1433 } else {
1434 snprintf(output_string, 64, "0 Mb/s");
1435 return RETURN_OK;
1436 }
developer06a01d92022-09-07 16:32:39 +08001437
developerbcc556a2022-09-22 20:02:45 +08001438 // Spatial streams
1439 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1440 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1441 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001442 }
developerbcc556a2022-09-22 20:02:45 +08001443
1444 // multiple 10 is to align duration unit (0.1 us)
1445 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1446 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1447
developer06a01d92022-09-07 16:32:39 +08001448 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1449
1450 return RETURN_OK;
1451}
1452#if 0
1453INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1454{
1455 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1456 char cmd[64];
1457 char buf[1024];
1458 int apIndex;
1459
1460 if (NULL == output_string)
1461 return RETURN_ERR;
1462
1463 apIndex=(radioIndex==0)?0:1;
1464
1465 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1466 _syscmd(cmd,buf, sizeof(buf));
1467
1468 snprintf(output_string, 64, "%s", buf);
1469 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1470 return RETURN_OK;
1471}
1472#endif
1473
1474
1475//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1476//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.
1477INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1478{
developer963da0c2022-09-13 15:58:27 +08001479 wifi_band band = band_invalid;
1480
developer06a01d92022-09-07 16:32:39 +08001481 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1482 if (NULL == output_string)
1483 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001484
1485 band = wifi_index_to_band(radioIndex);
1486
1487 memset(output_string, 0, 10);
1488 if (band == band_2_4)
1489 strcpy(output_string, "2.4GHz");
1490 else if (band == band_5)
1491 strcpy(output_string, "5GHz");
1492 else if (band == band_6)
1493 strcpy(output_string, "6GHz");
1494 else
1495 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1497
1498 return RETURN_OK;
1499#if 0
1500 char buf[MAX_BUF_SIZE]={'\0'};
1501 char str[MAX_BUF_SIZE]={'\0'};
1502 char cmd[MAX_CMD_SIZE]={'\0'};
1503 char *ch=NULL;
1504 char *ch2=NULL;
1505
1506 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1507 if (NULL == output_string)
1508 return RETURN_ERR;
1509
1510
1511 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1512
1513 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1514 {
1515 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1516 return RETURN_ERR;
1517 }
1518 ch=strchr(buf,'\n');
1519 *ch='\0';
1520 ch=strchr(buf,'=');
1521 if(ch==NULL)
1522 return RETURN_ERR;
1523
1524
1525 ch++;
1526
1527 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1528 strcpy(buf,"0");
1529 if(strlen(ch) == 1)
1530 ch=strcat(buf,ch);
1531
1532
1533 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1534
1535 if(_syscmd(cmd,str,64) == RETURN_ERR)
1536 {
1537 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1538 return RETURN_ERR;
1539 }
1540
1541
1542 ch2=strchr(str,'\n');
1543 //replace \n with \0
1544 *ch2='\0';
1545 ch2=strchr(str,'=');
1546 if(ch2==NULL)
1547 {
1548 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1549 return RETURN_ERR;
1550 }
1551 else
1552 wifi_dbg_printf("%s",ch2+1);
1553
1554
1555 ch2++;
1556
1557
1558 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1559
1560 memset(buf,'\0',sizeof(buf));
1561 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1562 {
1563 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1564 return RETURN_ERR;
1565 }
1566 if (strstr(buf,"2.4") != NULL )
1567 strcpy(output_string,"2.4GHz");
1568 else if(strstr(buf,"5.") != NULL )
1569 strcpy(output_string,"5GHz");
1570 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1571
1572 return RETURN_OK;
1573#endif
1574}
1575
1576//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1577//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.
1578INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1579{
1580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1581 if (NULL == output_string)
1582 return RETURN_ERR;
1583 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1584 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1585
1586 return RETURN_OK;
1587#if 0
1588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1589 char buf[MAX_BUF_SIZE]={'\0'};
1590 char str[MAX_BUF_SIZE]={'\0'};
1591 char cmd[MAX_CMD_SIZE]={'\0'};
1592 char *ch=NULL;
1593 char *ch2=NULL;
1594 char ch1[5]="0";
1595
1596 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1597
1598 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1599 {
1600 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1601 return RETURN_ERR;
1602 }
1603
1604 ch=strchr(buf,'\n');
1605 *ch='\0';
1606 ch=strchr(buf,'=');
1607 if(ch==NULL)
1608 return RETURN_ERR;
1609 ch++;
1610
1611 if(strlen(ch)==1)
1612 {
1613 strcat(ch1,ch);
1614
1615 }
1616 else
1617 {
1618 strcpy(ch1,ch);
1619 }
1620
1621
1622
1623 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1624 if(_syscmd(cmd,str,64) == RETURN_ERR)
1625 {
1626 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1627 return RETURN_ERR;
1628 }
1629
1630
1631 ch2=strchr(str,'\n');
1632 //replace \n with \0
1633 *ch2='\0';
1634 ch2=strchr(str,'=');
1635 if(ch2==NULL)
1636 {
1637 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1638 return RETURN_ERR;
1639 }
1640 else
1641 wifi_dbg_printf("%s",ch2+1);
1642 ch2++;
1643
1644
1645 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1646 memset(buf,'\0',sizeof(buf));
1647 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1648 {
1649 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1650 return RETURN_ERR;
1651 }
1652
1653
1654 if(strstr(buf,"2.4")!=NULL)
1655 {
1656 strcpy(output_string,"2.4GHz");
1657 }
1658 if(strstr(buf,"5.")!=NULL)
1659 {
1660 strcpy(output_string,"5GHz");
1661 }
1662 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1663 return RETURN_OK;
1664#endif
1665}
1666
1667//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1668//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.
1669INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1670{
developer963da0c2022-09-13 15:58:27 +08001671 char cmd[128]={0};
1672 char buf[128]={0};
1673 char temp_output[128] = {0};
1674 wifi_band band;
1675
1676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001677 if (NULL == output_string)
1678 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001679
1680 band = wifi_index_to_band(radioIndex);
1681 if (band == band_2_4) {
1682 strcat(temp_output, "b,g,");
1683 } else if (band == band_5) {
1684 strcat(temp_output, "a,");
1685 }
1686
1687 // ht capabilities
1688 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);
1689 _syscmd(cmd, buf, sizeof(buf));
1690 if (strncmp(buf, "0x00", 4) != 0) {
1691 strcat(temp_output, "n,");
1692 }
developer06a01d92022-09-07 16:32:39 +08001693
developer963da0c2022-09-13 15:58:27 +08001694 // vht capabilities
1695 if (band == band_5) {
1696 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1697 _syscmd(cmd, buf, sizeof(buf));
1698 if (strncmp(buf, "0x00000000", 10) != 0) {
1699 strcat(temp_output, "ac,");
1700 }
1701 }
1702
1703 // he capabilities
1704 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);
1705 _syscmd(cmd, buf, sizeof(buf));
1706 if (strncmp (buf, "0x0000", 6) != 0) {
1707 strcat(temp_output, "ax,");
1708 }
1709
1710 // Remove the last comma
1711 if (strlen(temp_output) != 0)
1712 temp_output[strlen(temp_output)-1] = '\0';
1713 strncpy(output_string, temp_output, strlen(temp_output));
1714 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001715 return RETURN_OK;
1716}
1717
1718//Get the radio operating mode, and pure mode flag. eg: "ac"
1719//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.
1720INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1721{
1722 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1723 if (NULL == output_string)
1724 return RETURN_ERR;
1725
1726 if (radioIndex == 0) {
1727 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1728 *gOnly = FALSE;
1729 *nOnly = TRUE;
1730 *acOnly = FALSE;
1731 } else {
1732 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1733 *gOnly = FALSE;
1734 *nOnly = FALSE;
1735 *acOnly = FALSE;
1736 }
1737 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1738
1739 return RETURN_OK;
1740#if 0
1741 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1742 char buf[64] = {0};
1743 char config_file[MAX_BUF_SIZE] = {0};
1744
1745 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1746 return RETURN_ERR;
1747
1748 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1749 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1750
1751 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1752 if (strlen(buf) == 0)
1753 {
1754 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1755 return RETURN_ERR;
1756 }
1757 if(strcmp(buf,"g")==0)
1758 {
1759 wifi_dbg_printf("\nG\n");
1760 *gOnly=TRUE;
1761 *nOnly=FALSE;
1762 *acOnly=FALSE;
1763 }
1764 else if(strcmp(buf,"n")==0)
1765 {
1766 wifi_dbg_printf("\nN\n");
1767 *gOnly=FALSE;
1768 *nOnly=TRUE;
1769 *acOnly=FALSE;
1770 }
1771 else if(strcmp(buf,"ac")==0)
1772 {
1773 wifi_dbg_printf("\nac\n");
1774 *gOnly=FALSE;
1775 *nOnly=FALSE;
1776 *acOnly=TRUE;
1777 }
1778 /* hostapd-5G.conf has "a" as hw_mode */
1779 else if(strcmp(buf,"a")==0)
1780 {
1781 wifi_dbg_printf("\na\n");
1782 *gOnly=FALSE;
1783 *nOnly=FALSE;
1784 *acOnly=FALSE;
1785 }
1786 else
1787 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1788
1789 //for a,n mode
1790 if(radioIndex == 1)
1791 {
1792 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1793 if(strcmp(buf,"1")==0)
1794 {
1795 strncpy(output_string, "n", 1);
1796 *nOnly=FALSE;
1797 }
1798 }
1799
1800 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1801 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1802 return RETURN_OK;
1803#endif
1804}
1805
developerdb744382022-09-13 15:34:54 +08001806INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1807{
1808 char cmd[128] = {0};
1809 char buf[64] = {0};
1810 char config_file[64] = {0};
1811 wifi_band band;
1812
1813 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1814 if(NULL == output_string || NULL == pureMode)
1815 return RETURN_ERR;
1816
1817 // grep all of the ieee80211 protocol config set to 1
1818 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1819 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1820 _syscmd(cmd, buf, sizeof(buf));
1821
1822 band = wifi_index_to_band(radioIndex);
1823 // puremode is a bit map
1824 *pureMode = 0;
1825 if (band == band_2_4) {
1826 strcat(output_string, "b,g");
1827 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1828 if (strstr(buf, "n") != NULL) {
1829 strcat(output_string, ",n");
1830 *pureMode |= WIFI_MODE_N;
1831 }
1832 if (strstr(buf, "ax") != NULL) {
1833 strcat(output_string, ",ax");
1834 *pureMode |= WIFI_MODE_AX;
1835 }
1836 } else if (band == band_5) {
1837 strcat(output_string, "a");
1838 *pureMode |= WIFI_MODE_A;
1839 if (strstr(buf, "n") != NULL) {
1840 strcat(output_string, ",n");
1841 *pureMode |= WIFI_MODE_N;
1842 }
1843 if (strstr(buf, "ac") != NULL) {
1844 strcat(output_string, ",ac");
1845 *pureMode |= WIFI_MODE_AC;
1846 }
1847 if (strstr(buf, "ax") != NULL) {
1848 strcat(output_string, ",ax");
1849 *pureMode |= WIFI_MODE_AX;
1850 }
1851 } else if (band == band_6) {
1852 if (strstr(buf, "ax") != NULL) {
1853 strcat(output_string, "ax");
1854 *pureMode |= WIFI_MODE_AX;
1855 }
1856 }
1857
1858 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1859 return RETURN_OK;
1860}
1861
1862// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001863INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1864{
1865 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1866 if (strcmp (channelMode,"11A") == 0)
1867 {
1868 writeBandWidth(radioIndex,"20MHz");
1869 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1870 printf("\nChannel Mode is 802.11a (5GHz)\n");
1871 }
1872 else if (strcmp (channelMode,"11NAHT20") == 0)
1873 {
1874 writeBandWidth(radioIndex,"20MHz");
1875 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1876 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1877 }
1878 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1879 {
1880 writeBandWidth(radioIndex,"40MHz");
1881 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1882 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1883 }
1884 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1885 {
1886 writeBandWidth(radioIndex,"40MHz");
1887 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1888 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1889 }
1890 else if (strcmp (channelMode,"11ACVHT20") == 0)
1891 {
1892 writeBandWidth(radioIndex,"20MHz");
1893 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1894 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1895 }
1896 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1897 {
1898 writeBandWidth(radioIndex,"40MHz");
1899 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1900 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1901 }
1902 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1903 {
1904 writeBandWidth(radioIndex,"40MHz");
1905 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1906 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1907 }
1908 else if (strcmp (channelMode,"11ACVHT80") == 0)
1909 {
1910 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1911 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1912 }
1913 else if (strcmp (channelMode,"11ACVHT160") == 0)
1914 {
1915 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1916 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1917 }
1918 else if (strcmp (channelMode,"11B") == 0)
1919 {
1920 writeBandWidth(radioIndex,"20MHz");
1921 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1922 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1923 }
1924 else if (strcmp (channelMode,"11G") == 0)
1925 {
1926 writeBandWidth(radioIndex,"20MHz");
1927 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1928 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1929 }
1930 else if (strcmp (channelMode,"11NGHT20") == 0)
1931 {
1932 writeBandWidth(radioIndex,"20MHz");
1933 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1934 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1935 }
1936 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1937 {
1938 writeBandWidth(radioIndex,"40MHz");
1939 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1940 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1941 }
1942 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1943 {
1944 writeBandWidth(radioIndex,"40MHz");
1945 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1946 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1947 }
1948 else
1949 {
1950 return RETURN_ERR;
1951 }
1952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1953
1954 return RETURN_OK;
1955}
1956
developerdb744382022-09-13 15:34:54 +08001957// Set the radio operating mode, and pure mode flag.
1958INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1959{
1960 int num_hostapd_support_mode = 3; // n, ac, ax
1961 struct params list[num_hostapd_support_mode];
1962 char config_file[64] = {0};
1963 char bandwidth[16] = {0};
1964 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08001965
developerdb744382022-09-13 15:34:54 +08001966
1967 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1968 // Set radio mode
1969 list[0].name = "ieee80211n";
1970 list[1].name = "ieee80211ac";
1971 list[2].name = "ieee80211ax";
1972 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1973
1974 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08001975 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08001976 list[0].value = "1";
1977 else
1978 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08001979 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08001980 list[1].value = "1";
1981 else
1982 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08001983 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08001984 list[2].value = "1";
1985 else
1986 list[2].value = "0";
1987 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1988
1989 if (channelMode == NULL || strlen(channelMode) == 0)
1990 return RETURN_OK;
1991 // Set bandwidth
1992 if (strstr(channelMode, "40") != NULL)
1993 strcpy(bandwidth, "40MHz");
1994 else if (strstr(channelMode, "80") != NULL)
1995 strcpy(bandwidth, "80MHz");
1996 else if (strstr(channelMode, "160") != NULL)
1997 strcpy(bandwidth, "160MHz");
1998 else // 11A, 11B, 11G....
1999 strcpy(bandwidth, "20MHz");
2000
2001 writeBandWidth(radioIndex, bandwidth);
2002 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2003
2004 wifi_reloadAp(radioIndex);
2005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2006
2007 return RETURN_OK;
2008}
2009
developer1d12ebf2022-10-04 15:13:38 +08002010INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2011
2012 char config_file[64] = {0};
2013 struct params params = {0};
2014 wifi_band band = band_invalid;
2015
2016 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2017
2018 band = wifi_index_to_band(radioIndex);
2019 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 || band != band_6))
2020 return RETURN_ERR;
2021 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2022 return RETURN_ERR;
2023
2024 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2025 params.name = "hw_mode";
2026 params.value = hw_mode;
2027 wifi_hostapdWrite(config_file, &params, 1);
2028 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2029
2030 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2031 return RETURN_OK;
2032}
2033
developer06a01d92022-09-07 16:32:39 +08002034//Get the list of supported channel. eg: "1-11"
2035//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.
2036INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2037{
developer6318ed52022-09-13 15:17:58 +08002038 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002039 if (NULL == output_string)
2040 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002041 char cmd[256] = {0};
2042 char buf[128] = {0};
2043 BOOL dfs_enable = false;
2044 // Parse possible channel number and separate them with commas.
2045 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer76989232022-10-04 14:13:19 +08002046 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002047 if (dfs_enable)
developer76989232022-10-04 14:13:19 +08002048 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
developer6318ed52022-09-13 15:17:58 +08002049 else
developer76989232022-10-04 14:13:19 +08002050 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
developer6318ed52022-09-13 15:17:58 +08002051
2052 _syscmd(cmd,buf,sizeof(buf));
2053 strncpy(output_string, buf, sizeof(buf));
2054
2055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2056 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002057}
2058
2059//Get the list for used channel. eg: "1,6,9,11"
2060//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.
2061INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2062{
2063 if (NULL == output_string)
2064 return RETURN_ERR;
2065 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
2066#if 0
2067 char IFName[50] ={0};
2068 char buf[MAX_BUF_SIZE] = {0};
2069 char cmd[MAX_CMD_SIZE] = {0};
2070 if (NULL == output_string)
2071 return RETURN_ERR;
2072
2073 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2074 if(radioIndex == 0)
2075 {
2076 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
2077 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'");
2078 }
2079 else if(radioIndex == 1)
2080 {
2081 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
2082 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'");
2083 }
2084 _syscmd(cmd,buf, sizeof(buf));
2085 if(strlen(buf) > 0)
2086 strcpy(output_string,buf);
2087 else
2088 strcpy(output_string,"0");
2089#endif
2090 return RETURN_OK;
2091}
2092
2093//Get the running channel number
2094INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2095{
developerda1ed692022-09-13 13:59:20 +08002096#ifdef MTK_IMPL
2097 if(!wifi_getApChannel(radioIndex, output_ulong))
2098 return RETURN_OK;
2099 else
2100 return RETURN_ERR;
2101#else
developer06a01d92022-09-07 16:32:39 +08002102 char cmd[1024] = {0}, buf[5] = {0};
2103
2104 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2105 if (NULL == output_ulong)
2106 return RETURN_ERR;
2107
2108 snprintf(cmd, sizeof(cmd),
2109 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2110 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2111 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2112 _syscmd(cmd, buf, sizeof(buf));
2113
2114 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2115 if (*output_ulong <= 0) {
2116 *output_ulong = 0;
2117 return RETURN_ERR;
2118 }
2119
2120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2121 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002122#endif
developer06a01d92022-09-07 16:32:39 +08002123}
2124
2125
2126INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2127{
2128 char cmd[1024] = {0}, buf[5] = {0};
2129 char interface_name[50] = {0};
2130
2131 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2132 if (NULL == output_ulong)
2133 return RETURN_ERR;
2134
2135 wifi_getApName(apIndex,interface_name);
2136 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2137 _syscmd(cmd,buf,sizeof(buf));
2138 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2139 if (*output_ulong == 0) {
2140 return RETURN_ERR;
2141 }
2142
2143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2144 return RETURN_OK;
2145}
2146
2147//Storing the previous channel value
2148INT wifi_storeprevchanval(INT radioIndex)
2149{
2150 char buf[256] = {0};
2151 char output[4]={'\0'};
2152 char config_file[MAX_BUF_SIZE] = {0};
2153 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2154 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2155 if(radioIndex == 0)
2156 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2157 else if(radioIndex == 1)
2158 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2159 system(buf);
2160 Radio_flag = FALSE;
2161 return RETURN_OK;
2162}
2163
2164//Set the running channel number
2165INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2166{
developer76989232022-10-04 14:13:19 +08002167 // We only write hostapd config here
2168 char str_channel[8]={0};
2169 char *list_channel;
2170 char config_file[128] = {0};
2171 char possible_channels[256] = {0};
2172 int max_radio_num = 0;
2173 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002174
developer76989232022-10-04 14:13:19 +08002175 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002176
developer76989232022-10-04 14:13:19 +08002177 // Check valid
2178 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002179
developer76989232022-10-04 14:13:19 +08002180 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2181 list_channel = strtok(possible_channels, ",");
2182 while(true)
developer06a01d92022-09-07 16:32:39 +08002183 {
developer76989232022-10-04 14:13:19 +08002184 if(list_channel == NULL) { // input not in the list
2185 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2186 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002187 }
developer76989232022-10-04 14:13:19 +08002188 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2189 break;
2190 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002191 }
2192
developer76989232022-10-04 14:13:19 +08002193 list.name = "channel";
2194 list.value = str_channel;
2195 wifi_getMaxRadioNumber(&max_radio_num);
2196 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002197 {
developer76989232022-10-04 14:13:19 +08002198 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2199 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002200 }
2201
developer76989232022-10-04 14:13:19 +08002202 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002203 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002204}
developer06a01d92022-09-07 16:32:39 +08002205
2206INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2207{
developer76989232022-10-04 14:13:19 +08002208 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002209 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002210 char config_file[64];
2211 int max_num_radios = 0;
2212 wifi_band band = band_invalid;
2213
2214 band = wifi_index_to_band(radioIndex);
2215 if (band == band_2_4)
2216 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002217
developer06a01d92022-09-07 16:32:39 +08002218 snprintf(str_idx, sizeof(str_idx), "%d", channel);
developer76989232022-10-04 14:13:19 +08002219 list[0].name = "vht_oper_centr_freq_seg0_idx";
2220 list[0].value = str_idx;
2221 list[1].name = "he_oper_centr_freq_seg0_idx";
2222 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002223
developer76989232022-10-04 14:13:19 +08002224 wifi_getMaxRadioNumber(&max_num_radios);
2225 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002226 {
developer76989232022-10-04 14:13:19 +08002227 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2228 if (band == band_6)
2229 wifi_hostapdWrite(config_file, &list[1], 1);
2230 else
2231 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002232 }
2233
2234 return RETURN_OK;
2235}
2236
2237//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2238//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2239INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2240{
2241 //Set to wifi config only. Wait for wifi reset to apply.
2242 char buf[256] = {0};
2243 char str_channel[256] = {0};
2244 int count = 0;
2245 ULONG Value = 0;
2246 FILE *fp = NULL;
2247 if(enable == TRUE)
2248 {
developer06a01d92022-09-07 16:32:39 +08002249 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002250 }
developer5884e982022-10-06 10:52:50 +08002251 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002252}
2253
developer0b246d12022-09-30 15:24:20 +08002254INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2255{
2256 if (output_bool == NULL)
2257 return RETURN_ERR;
2258
2259 *output_bool = TRUE;
2260
2261 return RETURN_OK;
2262}
2263
developer06a01d92022-09-07 16:32:39 +08002264INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2265{
2266 if (NULL == output_bool)
2267 return RETURN_ERR;
2268 *output_bool=FALSE;
2269 return RETURN_OK;
2270}
2271
2272INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2273{
2274 if (NULL == output_bool)
2275 return RETURN_ERR;
2276 *output_bool=FALSE;
2277 return RETURN_OK;
2278}
2279
2280INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2281{
2282 //Set to wifi config only. Wait for wifi reset to apply.
2283 return RETURN_OK;
2284}
2285
2286INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2287{
2288 return RETURN_OK;
2289}
2290
2291INT wifi_factoryResetAP(int apIndex)
2292{
developer838cca92022-10-03 13:19:57 +08002293 char ap_config_file[64] = {0};
2294 char cmd[128] = {0};
2295
developer06a01d92022-09-07 16:32:39 +08002296 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002297
2298 wifi_setApEnable(apIndex, FALSE);
2299 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2300 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2301 wifi_setApEnable(apIndex, TRUE);
2302
developer06a01d92022-09-07 16:32:39 +08002303 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002304
developer06a01d92022-09-07 16:32:39 +08002305 return RETURN_OK;
2306}
2307
2308//To set Band Steering AP group
2309//To-do
2310INT wifi_setBandSteeringApGroup(char *ApGroup)
2311{
2312 return RETURN_OK;
2313}
2314
developer1e5aa162022-09-13 16:06:24 +08002315INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2316{
2317 char config_file[128] = {'\0'};
2318 char buf[128] = {'\0'};
2319
2320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2321 if (dtimInterval == NULL)
2322 return RETURN_ERR;
2323
2324 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2325 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2326
2327 if (strlen(buf) == 0) {
2328 *dtimInterval = 2;
2329 } else {
2330 *dtimInterval = strtoul(buf, NULL, 10);
2331 }
2332
2333 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2334 return RETURN_OK;
2335}
2336
developer06a01d92022-09-07 16:32:39 +08002337INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2338{
developer5f222492022-09-13 15:21:52 +08002339 struct params params={0};
2340 char config_file[MAX_BUF_SIZE] = {'\0'};
2341 char buf[MAX_BUF_SIZE] = {'\0'};
2342
2343 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2344 if (dtimInterval < 1 || dtimInterval > 255) {
2345 return RETURN_ERR;
2346 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2347 }
2348
2349 params.name = "dtim_period";
2350 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2351 params.value = buf;
2352
2353 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2354 wifi_hostapdWrite(config_file, &params, 1);
2355 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2356
2357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2358 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002359}
2360
2361//Check if the driver support the Dfs
2362INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2363{
2364 if (NULL == output_bool)
2365 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002366 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002367 return RETURN_OK;
2368}
2369
2370//The output_string is a max length 256 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2371//The value of this parameter is a comma seperated list of channel number
2372INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2373{
2374 if (NULL == output_pool)
2375 return RETURN_ERR;
2376 if (radioIndex==1)
2377 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2378 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2379
2380 return RETURN_OK;
2381}
2382
2383INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2384{
2385 //Set to wifi config. And apply instantly.
2386 return RETURN_OK;
2387}
2388
2389INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2390{
2391 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2392 return RETURN_ERR;
2393 *output_interval_seconds=1800;
2394 *output_dwell_milliseconds=40;
2395
2396 return RETURN_OK;
2397}
2398
2399INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2400{
2401 //Set to wifi config. And apply instantly.
2402 return RETURN_OK;
2403}
2404
developerbfc18512022-10-05 17:54:28 +08002405INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2406{
2407 if (output_bool == NULL)
2408 return RETURN_ERR;
2409 *output_bool = true;
2410 return RETURN_OK;
2411}
2412
2413INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2414{
2415 return RETURN_OK;
2416}
2417
developer06a01d92022-09-07 16:32:39 +08002418//Get the Dfs enable status
2419INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2420{
developer9964b5b2022-09-13 15:59:34 +08002421 char buf[16] = {0};
2422 FILE *f = NULL;
2423 wifi_band band;
2424
2425 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2426
2427 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002428 if (NULL == output_bool)
2429 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002430
2431 band = wifi_index_to_band(radioIndex);
2432 if (band != band_5)
2433 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002434
developer9964b5b2022-09-13 15:59:34 +08002435 f = fopen(DFS_ENABLE_FILE, "r");
2436 if (f != NULL) {
2437 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002438 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002439 *output_bool = FALSE;
2440 fclose(f);
2441 }
2442 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002443 return RETURN_OK;
2444}
2445
2446//Set the Dfs enable status
2447INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2448{
developer9964b5b2022-09-13 15:59:34 +08002449 char config_file[128] = {0};
2450 FILE *f = NULL;
2451 struct params params={0};
2452 wifi_band band;
2453
2454 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2455
2456 band = wifi_index_to_band(radioIndex);
2457 if (band != band_5)
2458 return RETURN_OK;
2459
2460 f = fopen(DFS_ENABLE_FILE, "w");
2461 if (f == NULL)
2462 return RETURN_ERR;
2463 fprintf(f, "%d", enable);
2464 fclose(f);
2465
2466 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002467 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002468 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2469 wifi_hostapdWrite(config_file, &params, 1);
2470 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2471
2472 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2473
developer9964b5b2022-09-13 15:59:34 +08002474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002475 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002476}
2477
2478//Check if the driver support the AutoChannelRefreshPeriod
2479INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2480{
2481 if (NULL == output_bool)
2482 return RETURN_ERR;
2483 *output_bool=FALSE; //not support
2484
2485 return RETURN_OK;
2486}
2487
2488//Get the ACS refresh period in seconds
2489INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2490{
2491 if (NULL == output_ulong)
2492 return RETURN_ERR;
2493 *output_ulong=300;
2494
2495 return RETURN_OK;
2496}
2497
2498//Set the ACS refresh period in seconds
2499INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2500{
2501 return RETURN_ERR;
2502}
2503
2504//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2505//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.
2506INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2507{
developer70490032022-09-13 15:45:20 +08002508 char cmd[128] = {0}, buf[64] = {0};
2509 char interface_name[64] = {0};
2510 int ret = 0, len=0;
2511 BOOL radio_enable = FALSE;
2512
2513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2514
developer06a01d92022-09-07 16:32:39 +08002515 if (NULL == output_string)
2516 return RETURN_ERR;
2517
developer70490032022-09-13 15:45:20 +08002518 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2519 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002520
developer70490032022-09-13 15:45:20 +08002521 if (radio_enable != TRUE)
2522 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002523
developer70490032022-09-13 15:45:20 +08002524 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002525 ret = _syscmd(cmd, buf, sizeof(buf));
2526 len = strlen(buf);
2527 if((ret != 0) || (len == 0))
2528 {
2529 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2530 return RETURN_ERR;
2531 }
2532
2533 buf[len-1] = '\0';
2534 snprintf(output_string, 64, "%sMHz", buf);
2535 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2536
2537#if 0
2538 //TODO: revisit below implementation
2539 char output_buf[8]={0};
2540 char bw_value[10];
2541 char config_file[MAX_BUF_SIZE] = {0};
2542
2543 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2544 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2545 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2546 readBandWidth(radioIndex,bw_value);
2547
2548 if(strstr (output_buf,"0") != NULL )
2549 {
2550 strcpy(output_string,bw_value);
2551 }
2552 else if (strstr (output_buf,"1") != NULL)
2553 {
2554 strcpy(output_string,"80MHz");
2555 }
2556 else if (strstr (output_buf,"2") != NULL)
2557 {
2558 strcpy(output_string,"160MHz");
2559 }
2560 else if (strstr (output_buf,"3") != NULL)
2561 {
2562 strcpy(output_string,"80+80");
2563 }
2564 else
2565 {
2566 strcpy(output_string,"Auto");
2567 }
2568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2569#endif
2570
2571 return RETURN_OK;
2572}
2573
2574//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002575INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002576{
developerf7a466e2022-09-29 11:55:56 +08002577 char config_file[128];
2578 char set_value[16];
2579 struct params params[2];
2580 int max_radio_num = 0;
2581
developer06a01d92022-09-07 16:32:39 +08002582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002583
developerf7a466e2022-09-29 11:55:56 +08002584 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002585 return RETURN_ERR;
2586
developerf7a466e2022-09-29 11:55:56 +08002587 if(strstr(bandwidth,"80+80") != NULL)
2588 strcpy(set_value, "3");
2589 else if(strstr(bandwidth,"160") != NULL)
2590 strcpy(set_value, "2");
2591 else if(strstr(bandwidth,"80") != NULL)
2592 strcpy(set_value, "1");
2593 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2594 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002595 else
2596 {
developerf7a466e2022-09-29 11:55:56 +08002597 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002598 return RETURN_ERR;
2599 }
2600
developerf7a466e2022-09-29 11:55:56 +08002601 params[0].name = "vht_oper_chwidth";
2602 params[0].value = set_value;
2603 params[1].name = "he_oper_chwidth";
2604 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002605
developerf7a466e2022-09-29 11:55:56 +08002606 wifi_getMaxRadioNumber(&max_radio_num);
2607 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002608 {
developerf7a466e2022-09-29 11:55:56 +08002609 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2610 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002611 }
2612
2613 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2614 return RETURN_OK;
2615}
2616
2617//Getting current radio extension channel
2618INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2619{
2620 CHAR buf[150] = {0};
2621 CHAR cmd[150] = {0};
2622 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2623 _syscmd(cmd, buf, sizeof(buf));
2624 if(NULL != strstr(buf,"HT40+"))
2625 strcpy(Value,"AboveControlChannel");
2626 else if(NULL != strstr(buf,"HT40-"))
2627 strcpy(Value,"BelowControlChannel");
2628 return RETURN_OK;
2629}
2630
2631//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2632//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.
2633INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2634{
2635 if (NULL == output_string)
2636 return RETURN_ERR;
2637
2638 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2639#if 0
2640 CHAR Value[100] = {0};
2641 if (NULL == output_string)
2642 return RETURN_ERR;
2643 if(radioIndex == 0)
2644 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2645 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2646 {
2647 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2648 if(strcmp(Value,"40MHz") == 0)
2649 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2650 else
2651 strcpy(Value,"Auto");
2652 }
2653 strcpy(output_string,Value);
2654#endif
2655
2656 return RETURN_OK;
2657}
2658
2659//Set the extension channel.
2660INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2661{
2662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2663 struct params params={'\0'};
2664 char config_file[MAX_BUF_SIZE] = {0};
2665 char ext_channel[127]={'\0'};
2666
2667 params.name = "ht_capab";
2668
2669 if(radioIndex == 0)
2670 {
2671 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002672 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002673 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002674 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002675 else
developer3cc0f2e2022-09-15 18:25:39 +08002676 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002677 }
2678 else if(radioIndex == 1)
2679 {
2680 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002681 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002682 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002683 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002684 else
developer3cc0f2e2022-09-15 18:25:39 +08002685 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002686 }
2687
2688 params.value = ext_channel;
2689 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2690 {
2691 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2692 wifi_hostapdWrite(config_file, &params, 1);
2693 }
2694
2695 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2696 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2697 return RETURN_OK;
2698}
2699
2700//Get the guard interval value. eg "400nsec" or "800nsec"
2701//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.
2702INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2703{
developer454b9462022-09-13 15:29:16 +08002704 wifi_guard_interval_t GI;
2705
2706 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2707
2708 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002709 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002710
2711 if (GI == wifi_guard_interval_400)
2712 strcpy(output_string, "400nsec");
2713 else if (GI == wifi_guard_interval_800)
2714 strcpy(output_string, "800nsec");
2715 else if (GI == wifi_guard_interval_1600)
2716 strcpy(output_string, "1600nsec");
2717 else if (GI == wifi_guard_interval_3200)
2718 strcpy(output_string, "3200nsec");
2719 else
2720 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002721
developer454b9462022-09-13 15:29:16 +08002722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002723 return RETURN_OK;
2724}
2725
2726//Set the guard interval value.
2727INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2728{
developer454b9462022-09-13 15:29:16 +08002729 wifi_guard_interval_t GI;
2730 int ret = 0;
2731
2732 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2733
2734 if (strcmp(string, "400nsec") == 0)
2735 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002736 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002737 GI = wifi_guard_interval_800;
2738 else if (strcmp(string , "1600nsec") == 0)
2739 GI = wifi_guard_interval_1600;
2740 else if (strcmp(string , "3200nsec") == 0)
2741 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002742 else
2743 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002744
2745 ret = wifi_setGuardInterval(radioIndex, GI);
2746
2747 if (ret == RETURN_ERR) {
2748 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2749 return RETURN_ERR;
2750 }
2751
2752 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2753 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002754}
2755
2756//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2757INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2758{
developerf49437e2022-09-29 19:58:21 +08002759 char buf[32]={0};
2760 char mcs_file[64] = {0};
2761 char cmd[64] = {0};
2762 int mode_bitmap = 0;
2763
2764 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2765 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002766 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002767 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2768
2769 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2770 _syscmd(cmd, buf, sizeof(buf));
2771 if (strlen(buf) > 0)
2772 *output_int = strtol(buf, NULL, 10);
2773 else {
2774 // output the max MCS for the current radio mode
2775 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2776 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2777 return RETURN_ERR;
2778 }
2779 if (mode_bitmap & WIFI_MODE_AX) {
2780 *output_int = 11;
2781 } else if (mode_bitmap & WIFI_MODE_AC) {
2782 *output_int = 9;
2783 } else if (mode_bitmap & WIFI_MODE_N) {
2784 *output_int = 7;
2785 }
2786 }
2787 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002788
2789 return RETURN_OK;
2790}
2791
2792//Set the Modulation Coding Scheme index
2793INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2794{
developerf49437e2022-09-29 19:58:21 +08002795 // 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).
2796 char config_file[64] = {0};
2797 char set_value[16] = {0};
2798 char mcs_file[32] = {0};
2799 wifi_band band = band_invalid;
2800 struct params set_config = {0};
2801 FILE *f = NULL;
2802
2803 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2804
2805 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2806
2807 if (MCS > 11 || MCS < 0) {
2808 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2809 return RETURN_ERR;
2810 }
2811
2812 if (MCS <= 7)
2813 strcpy(set_value, "0");
2814 else if (MCS <= 9)
2815 strcpy(set_value, "1");
2816 else
2817 strcpy(set_value, "2");
2818
2819 set_config.name = "he_basic_mcs_nss_set";
2820 set_config.value = set_value;
2821
2822 wifi_hostapdWrite(config_file, &set_config, 1);
2823 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2824
2825 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2826 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2827 f = fopen(mcs_file, "w");
2828 if (f == NULL) {
2829 fprintf(stderr, "%s: fopen failed\n", __func__);
2830 return RETURN_ERR;
2831 }
2832 fprintf(f, "%d", MCS);
2833 fclose(f);
2834
2835 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2836 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002837}
2838
2839//Get supported Transmit Power list, eg : "0,25,50,75,100"
2840//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.
2841INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2842{
2843 if (NULL == output_list)
2844 return RETURN_ERR;
2845 snprintf(output_list, 64,"0,25,50,75,100");
2846 return RETURN_OK;
2847}
2848
developera5005b62022-09-13 15:43:35 +08002849//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002850//The transmite power level is in units of full power for this radio.
2851INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2852{
2853 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002854 char buf[16]={0};
2855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002856
developera5005b62022-09-13 15:43:35 +08002857 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002858 return RETURN_ERR;
2859
developera5005b62022-09-13 15:43:35 +08002860 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 +08002861 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002862
developera5005b62022-09-13 15:43:35 +08002863 *output_ulong = strtol(buf, NULL, 10);
2864
2865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002866 return RETURN_OK;
2867}
2868
2869//Set Transmit Power
2870//The transmite power level is in units of full power for this radio.
2871INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2872{
developera5005b62022-09-13 15:43:35 +08002873 char *support;
developer06a01d92022-09-07 16:32:39 +08002874 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002875 char buf[128]={0};
2876 char txpower_str[64] = {0};
2877 int txpower = 0;
2878 int maximum_tx = 0;
2879
2880 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002881
developera5005b62022-09-13 15:43:35 +08002882 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 +08002883 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002884 maximum_tx = strtol(buf, NULL, 10);
2885
2886 // Get the Tx power supported list and check that is the input in the list
2887 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2888 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2889 support = strtok(buf, ",");
2890 while(true)
2891 {
2892 if(support == NULL) { // input not in the list
2893 wifi_dbg_printf("Input value is invalid.\n");
2894 return RETURN_ERR;
2895 }
2896 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2897 break;
2898 }
2899 support = strtok(NULL, ",");
2900 }
2901 txpower = TransmitPower*maximum_tx/100;
2902 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2903 _syscmd(cmd, buf, sizeof(buf));
2904 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002905
2906 return RETURN_OK;
2907}
2908
2909//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2910INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2911{
2912 if (NULL == Supported)
2913 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002914 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002915
2916 return RETURN_OK;
2917}
2918
2919//Get 80211h feature enable
2920INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2921{
developer3885fec2022-09-13 15:13:47 +08002922 char buf[64]={'\0'};
2923 char config_file[64] = {'\0'};
2924
2925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2926 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002927 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002928
2929 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2930 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002931
developer3885fec2022-09-13 15:13:47 +08002932 if (strncmp(buf, "1", 1) == 0)
2933 *enable = TRUE;
2934 else
2935 *enable = FALSE;
2936
2937 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002938 return RETURN_OK;
2939}
2940
2941//Set 80211h feature enable
2942INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2943{
developer3885fec2022-09-13 15:13:47 +08002944 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2945 struct params params={'\0'};
2946 char config_file[MAX_BUF_SIZE] = {0};
2947
2948 params.name = "ieee80211h";
2949
2950 if (enable) {
2951 params.value = "1";
2952 } else {
2953 params.value = "0";
2954 }
2955
2956 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2957 wifi_hostapdWrite(config_file, &params, 1);
2958
2959 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2960 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2961 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002962}
2963
2964//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.
2965INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2966{
2967 if (NULL == output)
2968 return RETURN_ERR;
2969 *output=100;
2970
2971 return RETURN_OK;
2972}
2973
2974//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.
2975INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2976{
2977 if (NULL == output)
2978 return RETURN_ERR;
2979 *output = -99;
2980
2981 return RETURN_OK;
2982}
2983
2984INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2985{
2986 return RETURN_ERR;
2987}
2988
2989
2990//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2991INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2992{
developer5f222492022-09-13 15:21:52 +08002993 char cmd[MAX_BUF_SIZE]={'\0'};
2994 char buf[MAX_CMD_SIZE]={'\0'};
2995
2996 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2997 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08002998 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002999
3000 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3001 _syscmd(cmd, buf, sizeof(buf));
3002 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003003
developer5f222492022-09-13 15:21:52 +08003004 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003005 return RETURN_OK;
3006}
3007
3008INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3009{
developer5f222492022-09-13 15:21:52 +08003010 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3011 struct params params={'\0'};
3012 char buf[MAX_BUF_SIZE] = {'\0'};
3013 char config_file[MAX_BUF_SIZE] = {'\0'};
3014
3015 params.name = "beacon_int";
3016 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3017 params.value = buf;
3018
3019 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3020 wifi_hostapdWrite(config_file, &params, 1);
3021
3022 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3023 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3024 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003025}
3026
3027//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.
3028INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3029{
developer06a01d92022-09-07 16:32:39 +08003030 //TODO: need to revisit below implementation
3031 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003032 char temp_output[128] = {0};
3033 char temp_TransmitRates[64] = {0};
3034 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003035
3036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3037 if (NULL == output)
3038 return RETURN_ERR;
3039 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003040 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3041
3042 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3043 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3044 } else {
3045 temp = strtok(temp_TransmitRates," ");
3046 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003047 {
developere9d0abd2022-09-13 15:40:57 +08003048 // Convert 100 kbps to Mbps
3049 temp[strlen(temp)-1]=0;
3050 if((temp[0]=='5') && (temp[1]=='\0'))
3051 {
3052 temp="5.5";
3053 }
3054 strcat(temp_output,temp);
3055 temp = strtok(NULL," ");
3056 if(temp!=NULL)
3057 {
3058 strcat(temp_output,",");
3059 }
developer06a01d92022-09-07 16:32:39 +08003060 }
developere9d0abd2022-09-13 15:40:57 +08003061 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003062 }
developer06a01d92022-09-07 16:32:39 +08003063 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003064 return RETURN_OK;
3065}
3066
3067INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3068{
3069 char *temp;
3070 char temp1[128];
3071 char temp_output[128];
3072 char temp_TransmitRates[128];
3073 char set[128];
3074 char sub_set[128];
3075 int set_count=0,subset_count=0;
3076 int set_index=0,subset_index=0;
3077 char *token;
3078 int flag=0, i=0;
3079 struct params params={'\0'};
3080 char config_file[MAX_BUF_SIZE] = {0};
3081
3082 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3083 if(NULL == TransmitRates)
3084 return RETURN_ERR;
3085 strcpy(sub_set,TransmitRates);
3086
3087 //Allow only supported Data transmit rate to be set
3088 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3089 token = strtok(sub_set,",");
3090 while( token != NULL ) /* split the basic rate to be set, by comma */
3091 {
3092 sub_set[subset_count]=atoi(token);
3093 subset_count++;
3094 token=strtok(NULL,",");
3095 }
3096 token=strtok(set,",");
3097 while(token!=NULL) /* split the supported rate by comma */
3098 {
3099 set[set_count]=atoi(token);
3100 set_count++;
3101 token=strtok(NULL,",");
3102 }
3103 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3104 {
3105 for(set_index=0;set_index < set_count;set_index++)
3106 {
3107 flag=0;
3108 if(sub_set[subset_index]==set[set_index])
3109 break;
3110 else
3111 flag=1; /* No match found */
3112 }
3113 if(flag==1)
3114 return RETURN_ERR; //If value not found return Error
3115 }
3116 strcpy(temp_TransmitRates,TransmitRates);
3117
3118 for(i=0;i<strlen(temp_TransmitRates);i++)
3119 {
3120 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3121 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3122 {
3123 continue;
3124 }
3125 else
3126 {
3127 return RETURN_ERR;
3128 }
3129 }
3130 strcpy(temp_output,"");
3131 temp = strtok(temp_TransmitRates,",");
3132 while(temp!=NULL)
3133 {
3134 strcpy(temp1,temp);
3135 if(radioIndex==1)
3136 {
3137 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3138 {
3139 return RETURN_ERR;
3140 }
3141 }
3142
3143 if(strcmp(temp,"5.5")==0)
3144 {
3145 strcpy(temp1,"55");
3146 }
3147 else
3148 {
3149 strcat(temp1,"0");
3150 }
3151 strcat(temp_output,temp1);
3152 temp = strtok(NULL,",");
3153 if(temp!=NULL)
3154 {
3155 strcat(temp_output," ");
3156 }
3157 }
3158 strcpy(TransmitRates,temp_output);
3159
3160 params.name= "basic_rates";
3161 params.value =TransmitRates;
3162
3163 wifi_dbg_printf("\n%s:",__func__);
3164 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3165 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3166 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3167 wifi_hostapdWrite(config_file,&params,1);
3168 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3169 return RETURN_OK;
3170}
3171
3172//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3173INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3174{
3175 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3176 FILE *fp = NULL;
3177 char path[256] = {0}, output_string[256] = {0};
3178 int count = 0;
3179 char *interface = NULL;
3180
3181 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3182 if (fp == NULL)
3183 {
3184 printf("Failed to run command in Function %s\n", __FUNCTION__);
3185 return RETURN_ERR;
3186 }
3187 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3188 {
3189 interface = strchr(path, '=');
3190
3191 if (interface != NULL)
3192 {
3193 strcpy(output_string, interface + 1);
3194 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3195 interface_name[count] = output_string[count];
3196
3197 interface_name[count] = '\0';
3198 }
3199 }
3200 pclose(fp);
3201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3202 return RETURN_OK;
3203}
3204
3205INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3206{
3207 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3208 output_struct->radio_BytesSent = 0;
3209 output_struct->radio_BytesReceived = 0;
3210 output_struct->radio_PacketsSent = 0;
3211 output_struct->radio_PacketsReceived = 0;
3212 output_struct->radio_ErrorsSent = 0;
3213 output_struct->radio_ErrorsReceived = 0;
3214 output_struct->radio_DiscardPacketsSent = 0;
3215 output_struct->radio_DiscardPacketsReceived = 0;
3216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3217 return RETURN_OK;
3218}
3219
3220
3221INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3222{
3223 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3224 CHAR buf[MAX_CMD_SIZE] = {0};
3225 CHAR Value[MAX_BUF_SIZE] = {0};
3226 FILE *fp = NULL;
3227
3228 if (ifname == NULL || strlen(ifname) <= 1)
3229 return RETURN_OK;
3230
3231 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3232 system(buf);
3233
3234 fp = fopen("/tmp/Radio_Stats.txt", "r");
3235 if(fp == NULL)
3236 {
3237 printf("/tmp/Radio_Stats.txt not exists \n");
3238 return RETURN_ERR;
3239 }
3240 fclose(fp);
3241
3242 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3243 File_Reading(buf, Value);
3244 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3245
3246 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3247 File_Reading(buf, Value);
3248 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3249
3250 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3251 File_Reading(buf, Value);
3252 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3253
3254 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3255 File_Reading(buf, Value);
3256 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3257
3258 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3259 File_Reading(buf, Value);
3260 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3261
3262 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3263 File_Reading(buf, Value);
3264 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3265
3266 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3267 File_Reading(buf, Value);
3268 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3269
3270 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3271 File_Reading(buf, Value);
3272 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3273
3274 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3275 return RETURN_OK;
3276}
3277
3278INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3279{
3280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3281 CHAR buf[MAX_CMD_SIZE] = {0};
3282 FILE *fp = NULL;
3283 INT count = 0;
3284
3285 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3286 {
3287 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3288 File_Reading(buf, status);
3289 }
3290 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3291 return RETURN_OK;
3292}
3293
3294//Get detail radio traffic static info
3295INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3296{
3297
3298#if 0
3299 //ifconfig radio_x
3300 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3301 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3302 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3303 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3304
3305 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3306 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3307 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.
3308 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.
3309
3310 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3311 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].
3312 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3313 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.
3314 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
3315 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
3316 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
3317 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
3318 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
3319
3320 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
3321 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
3322 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
3323 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.
3324
3325 return RETURN_OK;
3326#endif
3327
developera91d99f2022-09-29 15:59:10 +08003328 CHAR interface_name[64] = {0};
3329 CHAR config_path[64] = {0};
3330 BOOL iface_status = FALSE;
3331 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003332
3333 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3334 if (NULL == output_struct)
3335 return RETURN_ERR;
3336
developera91d99f2022-09-29 15:59:10 +08003337 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3338 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003339
developera91d99f2022-09-29 15:59:10 +08003340 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003341
developera91d99f2022-09-29 15:59:10 +08003342 if (iface_status == TRUE)
3343 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3344 else
3345 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003346
developera91d99f2022-09-29 15:59:10 +08003347 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3348 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3349 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3350 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3351 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3352 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3353 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3354 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003355
3356 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3357 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].
3358 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3359 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.
3360 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
3361 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
3362 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
3363 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
3364 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
3365
3366 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
3367 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
3368 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
3369 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.
3370
3371 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3372
3373 return RETURN_OK;
3374}
3375
3376//Set radio traffic static Measureing rules
3377INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3378{
3379 //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
3380 // Else, save the MeasuringRate and MeasuringInterval for future usage
3381
3382 return RETURN_OK;
3383}
3384
3385//To start or stop RadioTrafficStats
3386INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3387{
3388 //zqiu: If the RadioTrafficStats process running
3389 // if(enable)
3390 // return RETURN_OK.
3391 // else
3392 // Stop RadioTrafficStats process
3393 // Else
3394 // if(enable)
3395 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3396 // else
3397 // return RETURN_OK.
3398
3399 return RETURN_OK;
3400}
3401
3402//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
3403INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3404{
3405 //zqiu: Please ignor signalIndex.
3406 if (NULL == SignalLevel)
3407 return RETURN_ERR;
3408 *SignalLevel=(radioIndex==0)?-19:-19;
3409
3410 return RETURN_OK;
3411}
3412
3413//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3414INT wifi_applyRadioSettings(INT radioIndex)
3415{
3416 return RETURN_OK;
3417}
3418
3419//Get the radio index assocated with this SSID entry
3420INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3421{
3422 if (NULL == radioIndex)
3423 return RETURN_ERR;
3424 *radioIndex=ssidIndex%2;
3425
3426 return RETURN_OK;
3427}
3428
3429//Device.WiFi.SSID.{i}.Enable
3430//Get SSID enable configuration parameters (not the SSID enable status)
3431INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3432{
3433 if (NULL == output_bool)
3434 return RETURN_ERR;
3435
3436 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3437 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3438 return wifi_getApEnable(ssidIndex, output_bool);
3439}
3440
3441//Device.WiFi.SSID.{i}.Enable
3442//Set SSID enable configuration parameters
3443INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3444{
3445 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3446 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3447 return wifi_setApEnable(ssidIndex, enable);
3448}
3449
3450//Device.WiFi.SSID.{i}.Status
3451//Get the SSID enable status
3452INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3453{
3454 char cmd[MAX_CMD_SIZE]={0};
3455 char buf[MAX_BUF_SIZE]={0};
3456 BOOL output_bool;
3457
3458 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3459 if (NULL == output_string)
3460 return RETURN_ERR;
3461 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3462 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3463
3464 wifi_getApEnable(ssidIndex,&output_bool);
3465 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3466
3467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3468 return RETURN_OK;
3469}
3470
3471// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3472INT wifi_getSSIDName(INT apIndex, CHAR *output)
3473{
3474 char config_file[MAX_BUF_SIZE] = {0};
3475
3476 if (NULL == output)
3477 return RETURN_ERR;
3478
3479 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3480 wifi_hostapdRead(config_file,"ssid",output,32);
3481
3482 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3483 return RETURN_OK;
3484}
3485
3486// Set a max 32 byte string and sets an internal variable to the SSID name
3487INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3488{
3489 char str[MAX_BUF_SIZE]={'\0'};
3490 char cmd[MAX_CMD_SIZE]={'\0'};
3491 struct params params;
3492 char config_file[MAX_BUF_SIZE] = {0};
3493
3494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3495 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3496 return RETURN_ERR;
3497
3498 params.name = "ssid";
3499 params.value = ssid_string;
3500 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3501 wifi_hostapdWrite(config_file, &params, 1);
3502 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3503 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3504
3505 return RETURN_OK;
3506}
3507
3508//Get the BSSID
3509INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3510{
3511 char cmd[MAX_CMD_SIZE]="";
3512
3513 if (NULL == output_string)
3514 return RETURN_ERR;
3515
3516 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3517 {
3518 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3519 _syscmd(cmd, output_string, 64);
3520 return RETURN_OK;
3521 }
3522 strncpy(output_string, "\0", 1);
3523
3524 return RETURN_ERR;
3525}
3526
3527//Get the MAC address associated with this Wifi SSID
3528INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3529{
3530 wifi_getBaseBSSID(ssidIndex,output_string);
3531 return RETURN_OK;
3532}
3533
3534//Get the basic SSID traffic static info
3535//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3536//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3537INT wifi_applySSIDSettings(INT ssidIndex)
3538{
3539 BOOL status = false;
3540 char cmd[MAX_CMD_SIZE] = {0};
3541 char buf[MAX_CMD_SIZE] = {0};
3542 int apIndex, ret;
3543 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3544
3545 wifi_getApEnable(ssidIndex,&status);
3546 // Do not apply when ssid index is disabled
3547 if (status == false)
3548 return RETURN_OK;
3549
3550 /* Doing full remove and add for ssid Index
3551 * Not all hostapd options are supported with reload
3552 * for example macaddr_acl
3553 */
3554 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3555 return RETURN_ERR;
3556
3557 ret = wifi_setApEnable(ssidIndex,true);
3558
3559 /* Workaround for hostapd issue with multiple bss definitions
3560 * when first created interface will be removed
3561 * then all vaps other vaps on same phy are removed
3562 * after calling setApEnable to false readd all enabled vaps */
3563 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3564 apIndex = 2*i+radioIndex;
3565 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3566 _syscmd(cmd, buf, sizeof(buf));
3567 if(*buf == '1')
3568 wifi_setApEnable(apIndex, true);
3569 }
3570
3571 return ret;
3572}
3573
developera3c68b92022-09-13 15:27:29 +08003574struct channels_noise {
3575 int channel;
3576 int noise;
3577};
3578
3579// Return noise array for each channel
3580int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3581{
3582 FILE *f = NULL;
3583 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003584 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003585 size_t len = 0;
3586 ssize_t read = 0;
3587 int tmp = 0, arr_index = -1;
3588
3589 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3590
3591 if ((f = popen(cmd, "r")) == NULL) {
3592 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3593 return RETURN_ERR;
3594 }
developer5550e242022-09-30 09:59:32 +08003595
3596 while(fgets(line, sizeof(line), f) != NULL) {
3597 if(arr_index < channels_num){
3598 sscanf(line, "%d", &tmp);
3599 if (tmp > 0) { // channel frequency, the first line must be frequency
3600 arr_index++;
3601 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3602 } else { // noise
3603 channels_noise_arr[arr_index].noise = tmp;
3604 }
3605 }else{
3606 break;
developera3c68b92022-09-13 15:27:29 +08003607 }
3608 }
developera3c68b92022-09-13 15:27:29 +08003609 pclose(f);
3610 return RETURN_OK;
3611}
3612
developer06a01d92022-09-07 16:32:39 +08003613//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3614//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3615INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3616{
developera3c68b92022-09-13 15:27:29 +08003617 int index = -1;
3618 wifi_neighbor_ap2_t *scan_array = NULL;
3619 char cmd[256]={0};
3620 char buf[128]={0};
3621 char file_name[32] = {0};
3622 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003623 char line[256] = {0};
3624 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003625 int freq=0;
3626 FILE *f = NULL;
3627 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003628 int channels_num = 0;
3629 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003630 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003631 bool filter_enable = false;
3632 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003633
developer615510b2022-09-27 10:14:35 +08003634 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003635
3636 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3637 f = fopen(file_name, "r");
3638 if (f != NULL) {
3639 fgets(filter_SSID, sizeof(file_name), f);
3640 if (strlen(filter_SSID) != 0)
3641 filter_enable = true;
3642 fclose(f);
3643 }
3644
3645 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003646 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003647 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003648
developer5550e242022-09-30 09:59:32 +08003649
developer06a01d92022-09-07 16:32:39 +08003650
developera3c68b92022-09-13 15:27:29 +08003651 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 +08003652 // 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 +08003653 fprintf(stderr, "cmd: %s\n", cmd);
3654 if ((f = popen(cmd, "r")) == NULL) {
3655 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3656 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003657 }
developer5550e242022-09-30 09:59:32 +08003658
3659 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3660 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3661
developer615510b2022-09-27 10:14:35 +08003662 ret = fgets(line, sizeof(line), f);
3663 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003664 if(strstr(line, "BSS") != NULL) { // new neighbor info
3665 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3666 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3667 // 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 +08003668
developera3c68b92022-09-13 15:27:29 +08003669 if (!filter_BSS) {
3670 index++;
3671 wifi_neighbor_ap2_t *tmp;
3672 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3673 if (tmp == NULL) { // no more memory to use
3674 index--;
3675 wifi_dbg_printf("%s: realloc failed\n", __func__);
3676 break;
3677 }
3678 scan_array = tmp;
3679 }
3680 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3681
3682 filter_BSS = false;
3683 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3684 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3685 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3686 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3687 } else if (strstr(line, "freq") != NULL) {
3688 sscanf(line," freq: %d", &freq);
3689 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3690
3691 if (freq >= 2412 && freq <= 2484) {
3692 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3693 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3694 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3695 }
3696 else if (freq >= 5160 && freq <= 5805) {
3697 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3698 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3699 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3700 }
3701
3702 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003703 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003704 for (int i = 0; i < channels_num; i++) {
3705 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3706 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3707 break;
3708 }
3709 }
3710 }
3711 } else if (strstr(line, "beacon interval") != NULL) {
3712 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3713 } else if (strstr(line, "signal") != NULL) {
3714 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3715 } else if (strstr(line,"SSID") != NULL) {
3716 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3717 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3718 filter_BSS = true;
3719 }
3720 } else if (strstr(line, "Supported rates") != NULL) {
3721 char SRate[80] = {0}, *tmp = NULL;
3722 memset(buf, 0, sizeof(buf));
3723 strcpy(SRate, line);
3724 tmp = strtok(SRate, ":");
3725 tmp = strtok(NULL, ":");
3726 strcpy(buf, tmp);
3727 memset(SRate, 0, sizeof(SRate));
3728
3729 tmp = strtok(buf, " \n");
3730 while (tmp != NULL) {
3731 strcat(SRate, tmp);
3732 if (SRate[strlen(SRate) - 1] == '*') {
3733 SRate[strlen(SRate) - 1] = '\0';
3734 }
3735 strcat(SRate, ",");
3736
3737 tmp = strtok(NULL, " \n");
3738 }
3739 SRate[strlen(SRate) - 1] = '\0';
3740 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3741 } else if (strstr(line, "DTIM") != NULL) {
3742 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3743 } else if (strstr(line, "VHT capabilities") != NULL) {
3744 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3745 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3746 } else if (strstr(line, "HT capabilities") != NULL) {
3747 strcat(scan_array[index].ap_SupportedStandards, ",n");
3748 strcpy(scan_array[index].ap_OperatingStandards, "n");
3749 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003750 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003751 sscanf(line," * channel width: %d", &vht_channel_width);
3752 if(vht_channel_width == 1) {
3753 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3754 } else {
3755 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3756 }
3757 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3758 continue;
3759 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003760 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003761 sscanf(line," * secondary channel offset: %s", &buf);
3762 if (!strcmp(buf, "above")) {
3763 //40Mhz +
3764 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3765 }
3766 else if (!strcmp(buf, "below")) {
3767 //40Mhz -
3768 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3769 } else {
3770 //20Mhz
3771 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3772 }
3773 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3774 continue;
3775 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003776 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3777 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3778 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003779 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3780 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003781 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003782 else
developer615510b2022-09-27 10:14:35 +08003783 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003784 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003785 if (strstr(line, "HE80/5GHz") != NULL) {
3786 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3787 ret = fgets(line, sizeof(line), f);
3788 } else
3789 continue;
developera3c68b92022-09-13 15:27:29 +08003790 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003791 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003792 }
developer615510b2022-09-27 10:14:35 +08003793 continue;
developera3c68b92022-09-13 15:27:29 +08003794 } else if (strstr(line, "WPA") != NULL) {
3795 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3796 } else if (strstr(line, "RSN") != NULL) {
3797 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3798 } else if (strstr(line, "Group cipher") != NULL) {
3799 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3800 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3801 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3802 }
3803 }
developer615510b2022-09-27 10:14:35 +08003804 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003805 }
3806
3807 if (!filter_BSS) {
3808 *output_array_size = index + 1;
3809 } else {
3810 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3811 *output_array_size = index;
3812 }
3813 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003814 pclose(f);
developer5550e242022-09-30 09:59:32 +08003815 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003816 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003817 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003818}
3819
3820//>> Deprecated: used for old RDKB code.
3821INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3822{
3823 INT status = RETURN_ERR;
3824
3825 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3826 output_struct->wifi_PLCPErrorCount = 0;
3827 output_struct->wifi_FCSErrorCount = 0;
3828 output_struct->wifi_InvalidMACCount = 0;
3829 output_struct->wifi_PacketsOtherReceived = 0;
3830 output_struct->wifi_Noise = 0;
3831 status = RETURN_OK;
3832 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3833 return status;
3834}
3835
3836INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3837{
3838 char cmd[128];
3839 char buf[1280];
3840 char *pos = NULL;
3841
3842 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3843 if (NULL == output_struct)
3844 return RETURN_ERR;
3845
3846 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3847
3848 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3849 _syscmd(cmd, buf, sizeof(buf));
3850
3851 pos = buf;
3852 if ((pos = strstr(pos, "RX packets:")) == NULL)
3853 return RETURN_ERR;
3854 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3855
3856 if ((pos = strstr(pos, "TX packets:")) == NULL)
3857 return RETURN_ERR;
3858 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3859
3860 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3861 return RETURN_ERR;
3862 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3863
3864 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3865 return RETURN_ERR;
3866 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3867
3868 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3869 _syscmd(cmd, buf, sizeof(buf));
3870 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3871
3872#if 0
3873 //TODO: need to revisit below implementation
3874 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3875 char interface_name[MAX_BUF_SIZE] = {0};
3876 char interface_status[MAX_BUF_SIZE] = {0};
3877 char Value[MAX_BUF_SIZE] = {0};
3878 char buf[MAX_CMD_SIZE] = {0};
3879 char cmd[MAX_CMD_SIZE] = {0};
3880 FILE *fp = NULL;
3881
3882 if (NULL == output_struct) {
3883 return RETURN_ERR;
3884 }
3885
3886 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3887
3888 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3889 {
3890 if(apIndex == 0) //private_wifi for 2.4G
3891 {
3892 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3893 }
3894 else if(apIndex == 1) //private_wifi for 5G
3895 {
3896 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3897 }
3898 else if(apIndex == 4) //public_wifi for 2.4G
3899 {
3900 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3901 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3902 {
3903 return RETURN_ERR;
3904 }
3905 if(buf[0] == '#')//tp-link
3906 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3907 else//tenda
3908 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3909 }
3910 else if(apIndex == 5) //public_wifi for 5G
3911 {
3912 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3913 }
3914
3915 GetIfacestatus(interface_name, interface_status);
3916
3917 if(0 != strcmp(interface_status, "1"))
3918 return RETURN_ERR;
3919
3920 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3921 system(cmd);
3922
3923 fp = fopen("/tmp/SSID_Stats.txt", "r");
3924 if(fp == NULL)
3925 {
3926 printf("/tmp/SSID_Stats.txt not exists \n");
3927 return RETURN_ERR;
3928 }
3929 fclose(fp);
3930
3931 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3932 File_Reading(buf, Value);
3933 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3934
3935 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3936 File_Reading(buf, Value);
3937 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3938
3939 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3940 File_Reading(buf, Value);
3941 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3942
3943 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3944 File_Reading(buf, Value);
3945 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3946
3947 /* There is no specific parameter from caller to associate the value wifi_Associations */
3948 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3949 //_syscmd(cmd, buf, sizeof(buf));
3950 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3951 }
3952#endif
3953 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3954 return RETURN_OK;
3955}
3956
3957INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3958{
3959 char interface_name[MAX_BUF_SIZE] = {0};
3960 char interface_status[MAX_BUF_SIZE] = {0};
3961 char Value[MAX_BUF_SIZE] = {0};
3962 char buf[MAX_CMD_SIZE] = {0};
3963 char cmd[MAX_CMD_SIZE] = {0};
3964 FILE *fp = NULL;
3965
3966 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3967 if (NULL == output_struct)
3968 return RETURN_ERR;
3969
3970 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3971
3972 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3973 {
3974 if(apIndex == 0) //private_wifi for 2.4G
3975 {
3976 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3977 }
3978 else if(apIndex == 1) //private_wifi for 5G
3979 {
3980 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3981 }
3982 else if(apIndex == 4) //public_wifi for 2.4G
3983 {
3984 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3985 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3986 {
3987 return RETURN_ERR;
3988 }
3989 if(buf[0] == '#')
3990 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3991 else
3992 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3993 }
3994 else if(apIndex == 5) //public_wifi for 5G
3995 {
3996 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3997 }
3998
3999 GetIfacestatus(interface_name, interface_status);
4000
4001 if(0 != strcmp(interface_status, "1"))
4002 return RETURN_ERR;
4003
4004 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4005 system(cmd);
4006
4007 fp = fopen("/tmp/SSID_Stats.txt", "r");
4008 if(fp == NULL)
4009 {
4010 printf("/tmp/SSID_Stats.txt not exists \n");
4011 return RETURN_ERR;
4012 }
4013 fclose(fp);
4014
4015 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4016 File_Reading(buf, Value);
4017 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4018
4019 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4020 File_Reading(buf, Value);
4021 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4022
4023 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4024 File_Reading(buf, Value);
4025 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4026
4027 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4028 File_Reading(buf, Value);
4029 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4030 }
4031
4032 output_struct->wifi_UnicastPacketsSent = 0;
4033 output_struct->wifi_UnicastPacketsReceived = 0;
4034 output_struct->wifi_MulticastPacketsSent = 0;
4035 output_struct->wifi_MulticastPacketsReceived = 0;
4036 output_struct->wifi_BroadcastPacketsSent = 0;
4037 output_struct->wifi_BroadcastPacketsRecevied = 0;
4038 output_struct->wifi_UnknownPacketsReceived = 0;
4039
4040 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4041 return RETURN_OK;
4042}
4043
4044INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4045{
4046 INT status = RETURN_ERR;
4047
4048 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4049 //Below values should get updated from hal
4050 output_struct->wifi_RetransCount=0;
4051 output_struct->wifi_FailedRetransCount=0;
4052 output_struct->wifi_RetryCount=0;
4053 output_struct->wifi_MultipleRetryCount=0;
4054 output_struct->wifi_ACKFailureCount=0;
4055 output_struct->wifi_AggregatedPacketCount=0;
4056
4057 status = RETURN_OK;
4058 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4059
4060 return status;
4061}
4062
4063INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4064{
4065 INT status = RETURN_ERR;
4066 UINT index;
4067 wifi_neighbor_ap_t *pt=NULL;
4068
4069 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4070 *output_array_size=2;
4071 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4072 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4073 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4074 strcpy(pt->ap_Radio,"");
4075 strcpy(pt->ap_SSID,"");
4076 strcpy(pt->ap_BSSID,"");
4077 strcpy(pt->ap_Mode,"");
4078 pt->ap_Channel=1;
4079 pt->ap_SignalStrength=0;
4080 strcpy(pt->ap_SecurityModeEnabled,"");
4081 strcpy(pt->ap_EncryptionMode,"");
4082 strcpy(pt->ap_OperatingFrequencyBand,"");
4083 strcpy(pt->ap_SupportedStandards,"");
4084 strcpy(pt->ap_OperatingStandards,"");
4085 strcpy(pt->ap_OperatingChannelBandwidth,"");
4086 pt->ap_BeaconPeriod=1;
4087 pt->ap_Noise=0;
4088 strcpy(pt->ap_BasicDataTransferRates,"");
4089 strcpy(pt->ap_SupportedDataTransferRates,"");
4090 pt->ap_DTIMPeriod=1;
4091 pt->ap_ChannelUtilization = 1;
4092 }
4093
4094 status = RETURN_OK;
4095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4096
4097 return status;
4098}
4099
4100//----------------- AP HAL -------------------------------
4101
4102//>> Deprecated: used for old RDKB code.
4103INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4104{
4105 if (NULL == output_ulong || NULL == output_struct)
4106 return RETURN_ERR;
4107 *output_ulong = 0;
4108 *output_struct = NULL;
4109 return RETURN_OK;
4110}
4111
4112#ifdef HAL_NETLINK_IMPL
4113static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4114 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4115 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4116 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4117 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4118 char mac_addr[20];
4119 static int count=0;
4120 int rate=0;
4121
4122 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4123
4124 nla_parse(tb,
4125 NL80211_ATTR_MAX,
4126 genlmsg_attrdata(gnlh, 0),
4127 genlmsg_attrlen(gnlh, 0),
4128 NULL);
4129
4130 if(!tb[NL80211_ATTR_STA_INFO]) {
4131 fprintf(stderr, "sta stats missing!\n");
4132 return NL_SKIP;
4133 }
4134
4135
4136 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4137 fprintf(stderr, "failed to parse nested attributes!\n");
4138 return NL_SKIP;
4139 }
4140
4141 //devIndex starts from 1
4142 if( ++count == out->wifi_devIndex )
4143 {
4144 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4145 //Getting the mac addrress
4146 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4147
4148 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4149 fprintf(stderr, "failed to parse nested rate attributes!");
4150 return NL_SKIP;
4151 }
4152
4153 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4154 if(rinfo[NL80211_RATE_INFO_BITRATE])
4155 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4156 out->wifi_devTxRate = rate/10;
4157 }
4158
4159 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4160 fprintf(stderr, "failed to parse nested rate attributes!");
4161 return NL_SKIP;
4162 }
4163
4164 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4165 if(rinfo[NL80211_RATE_INFO_BITRATE])
4166 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4167 out->wifi_devRxRate = rate/10;
4168 }
4169 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4170 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4171
4172 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4173 count = 0; //starts the count for next cycle
4174 return NL_STOP;
4175 }
4176
4177 return NL_SKIP;
4178
4179}
4180#endif
4181
4182INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4183{
4184#ifdef HAL_NETLINK_IMPL
4185 Netlink nl;
4186 char if_name[10];
4187
4188 wifi_device_info_t info;
4189 info.wifi_devIndex = devIndex;
4190
4191 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4192
4193 nl.id = initSock80211(&nl);
4194
4195 if (nl.id < 0) {
4196 fprintf(stderr, "Error initializing netlink \n");
4197 return -1;
4198 }
4199
4200 struct nl_msg* msg = nlmsg_alloc();
4201
4202 if (!msg) {
4203 fprintf(stderr, "Failed to allocate netlink message.\n");
4204 nlfree(&nl);
4205 return -2;
4206 }
4207
4208 genlmsg_put(msg,
4209 NL_AUTO_PORT,
4210 NL_AUTO_SEQ,
4211 nl.id,
4212 0,
4213 NLM_F_DUMP,
4214 NL80211_CMD_GET_STATION,
4215 0);
4216
4217 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4218 nl_send_auto(nl.socket, msg);
4219 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4220 nl_recvmsgs(nl.socket, nl.cb);
4221 nlmsg_free(msg);
4222 nlfree(&nl);
4223
4224 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4225 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4226 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4227 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4228 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4229 return RETURN_OK;
4230#else
4231 //iw utility to retrieve station information
4232#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4233#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4234#define MACFILE "/tmp/wifi_AssoMac.txt"
4235#define TXRATEFILE "/tmp/wifi_txrate.txt"
4236#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4237 FILE *file = NULL;
4238 char if_name[10] = {'\0'};
4239 char pipeCmd[256] = {'\0'};
4240 char line[256];
4241 int count,device = 0;
4242
4243 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4244
4245 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4246 file = popen(pipeCmd, "r");
4247
4248 if(file == NULL)
4249 return RETURN_ERR; //popen failed
4250
4251 fgets(line, sizeof line, file);
4252 device = atoi(line);
4253 pclose(file);
4254
4255 if(device == 0)
4256 return RETURN_ERR; //No devices are connected
4257
4258 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4259 system(pipeCmd);
4260
4261 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4262
4263 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4264
4265 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4266
4267 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4268
4269 //devIndex starts from 1, ++count
4270 if((file = fopen(SIGNALFILE, "r")) != NULL )
4271 {
4272 for(count =0;fgets(line, sizeof line, file) != NULL;)
4273 {
4274 if (++count == devIndex)
4275 {
4276 output_struct->wifi_devSignalStrength = atoi(line);
4277 break;
4278 }
4279 }
4280 fclose(file);
4281 }
4282 else
4283 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4284
4285 if((file = fopen(MACFILE, "r")) != NULL )
4286 {
4287 for(count =0;fgets(line, sizeof line, file) != NULL;)
4288 {
4289 if (++count == devIndex)
4290 {
4291 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]);
4292 break;
4293 }
4294 }
4295 fclose(file);
4296 }
4297 else
4298 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4299
4300 if((file = fopen(TXRATEFILE, "r")) != NULL )
4301 {
4302 for(count =0;fgets(line, sizeof line, file) != NULL;)
4303 {
4304 if (++count == devIndex)
4305 {
4306 output_struct->wifi_devTxRate = atoi(line);
4307 break;
4308 }
4309 }
4310 fclose(file);
4311 }
4312 else
4313 fprintf(stderr,"fopen wifi_txrate.txt failed");
4314
4315 if((file = fopen(RXRATEFILE, "r")) != NULL)
4316 {
4317 for(count =0;fgets(line, sizeof line, file) != NULL;)
4318 {
4319 if (++count == devIndex)
4320 {
4321 output_struct->wifi_devRxRate = atoi(line);
4322 break;
4323 }
4324 }
4325 fclose(file);
4326 }
4327 else
4328 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4329
4330 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4331
4332 return RETURN_OK;
4333#endif
4334}
4335
4336INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4337{
4338 if (NULL == device)
4339 return RETURN_ERR;
4340 return RETURN_OK;
4341}
4342//<<
4343
4344
4345//--------------wifi_ap_hal-----------------------------
4346//enables CTS protection for the radio used by this AP
4347INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4348{
4349 //save config and Apply instantly
4350 return RETURN_ERR;
4351}
4352
4353// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4354INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4355{
developer463d39a2022-09-13 15:32:51 +08004356 char config_file[64] = {'\0'};
4357 char buf[64] = {'\0'};
4358 struct params list;
4359
4360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4361 list.name = "ht_coex";
4362 snprintf(buf, sizeof(buf), "%d", enable);
4363 list.value = buf;
4364
4365 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4366 wifi_hostapdWrite(config_file, &list, 1);
4367 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4368
4369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4370
4371 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004372}
4373
4374//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4375INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4376{
developerea4bcce2022-09-13 15:26:13 +08004377 char config_file[MAX_BUF_SIZE] = {'\0'};
4378 char buf[MAX_BUF_SIZE] = {'\0'};
4379 struct params list;
4380
4381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4382 if (threshold < 256 || threshold > 2346 )
4383 return RETURN_ERR;
4384 list.name = "fragm_threshold";
4385 snprintf(buf, sizeof(buf), "%d", threshold);
4386 list.value = buf;
4387
4388 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4389 wifi_hostapdWrite(config_file, &list, 1);
4390 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004391
developerea4bcce2022-09-13 15:26:13 +08004392 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004393
4394 return RETURN_OK;
4395}
4396
4397// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4398INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4399{
developer51a927d2022-09-13 15:42:22 +08004400 char config_file[64] = {'\0'};
4401 char cmd[128] = {'\0'};
4402 char buf[64] = {'\0'};
4403 char stbc_config[16] = {'\0'};
4404 wifi_band band;
4405 int iterator = 0;
4406 BOOL current_stbc = FALSE;
4407
4408 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4409
4410 band = wifi_index_to_band(radioIndex);
4411 if (band == band_invalid)
4412 return RETURN_ERR;
4413
4414 if (band == band_2_4)
4415 iterator = 1;
4416 else if (band == band_5)
4417 iterator = 2;
4418 else
4419 return RETURN_OK;
4420
4421 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4422
4423 // set ht and vht config
4424 for (int i = 0; i < iterator; i++) {
4425 memset(stbc_config, 0, sizeof(stbc_config));
4426 memset(cmd, 0, sizeof(cmd));
4427 memset(buf, 0, sizeof(buf));
4428 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4429 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4430 _syscmd(cmd, buf, sizeof(buf));
4431 if (strlen(buf) != 0)
4432 current_stbc = TRUE;
4433 if (current_stbc == STBC_Enable)
4434 continue;
4435
4436 if (STBC_Enable == TRUE) {
4437 // Append the STBC flags in capab config
4438 memset(cmd, 0, sizeof(cmd));
4439 if (i == 0)
4440 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4441 else
4442 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4443 _syscmd(cmd, buf, sizeof(buf));
4444 } else if (STBC_Enable == FALSE) {
4445 // Remove the STBC flags and remain other flags in capab
4446 memset(cmd, 0, sizeof(cmd));
4447 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4448 _syscmd(cmd, buf, sizeof(buf));
4449 memset(cmd, 0, sizeof(cmd));
4450 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4451 _syscmd(cmd, buf, sizeof(buf));
4452 }
4453 }
4454
4455 wifi_reloadAp(radioIndex);
4456
4457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4458 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004459}
4460
4461// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4462INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4463{
developer54e6b9f2022-09-28 14:41:20 +08004464 char AMSDU_file_path[64] = {0};
4465
4466 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4467
4468 if(output_bool == NULL)
4469 return RETURN_ERR;
4470
4471 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4472
4473 if (access(AMSDU_file_path, F_OK) == 0)
4474 *output_bool = TRUE;
4475 else
4476 *output_bool = FALSE;
4477
4478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4479 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004480}
4481
4482// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4483INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4484{
developer54e6b9f2022-09-28 14:41:20 +08004485 char cmd[64]={0};
4486 char buf[64]={0};
4487 char AMSDU_file_path[64] = {0};
4488
4489 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4490
4491 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4492 _syscmd(cmd, buf, sizeof(buf));
4493
4494 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4495 memset(cmd, 0, sizeof(cmd));
4496 if (amsduEnable == TRUE)
4497 sprintf(cmd, "touch %s", AMSDU_file_path);
4498 else
4499 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4500 _syscmd(cmd, buf, sizeof(buf));
4501
4502 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4503 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004504}
4505
4506//P2 // outputs the number of Tx streams
4507INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4508{
developer2de97692022-09-26 14:00:03 +08004509 char buf[8] = {0};
4510 char cmd[128] = {0};
4511
4512 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4513
4514 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4515 _syscmd(cmd, buf, sizeof(buf));
4516
4517 // if there is no record, output the max number of spatial streams
4518 if (strlen(buf) == 0) {
4519 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4520 _syscmd(cmd, buf, sizeof(buf));
4521 }
4522
4523 *output_int = (INT)strtol(buf, NULL, 10);
4524
4525 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4526
4527 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004528}
4529
4530//P2 // sets the number of Tx streams to an enviornment variable
4531INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4532{
developer2de97692022-09-26 14:00:03 +08004533 char cmd[128] = {0};
4534 char buf[128] = {0};
4535 char chain_mask_file[128] = {0};
4536 FILE *f = NULL;
4537
4538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4539
4540 if (numStreams == 0) {
4541 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4542 return RETURN_ERR;
4543 }
4544 wifi_setRadioEnable(radioIndex, FALSE);
4545 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4546 _syscmd(cmd, buf, sizeof(buf));
4547
4548 if (strlen(buf) > 0) {
4549 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4550 return RETURN_ERR;
4551 }
4552 wifi_setRadioEnable(radioIndex, TRUE);
4553
4554 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4555 f = fopen(chain_mask_file, "w");
4556 if (f == NULL) {
4557 fprintf(stderr, "%s: fopen failed.\n", __func__);
4558 return RETURN_ERR;
4559 }
4560 fprintf(f, "%d", numStreams);
4561 fclose(f);
4562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4563 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004564}
4565
4566//P2 // outputs the number of Rx streams
4567INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4568{
developer2de97692022-09-26 14:00:03 +08004569 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4570 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4571 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004572 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004573 }
4574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004575 return RETURN_OK;
4576}
4577
4578//P2 // sets the number of Rx streams to an enviornment variable
4579INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4580{
developer2de97692022-09-26 14:00:03 +08004581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4582 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4583 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4584 return RETURN_ERR;
4585 }
4586 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004587 return RETURN_ERR;
4588}
4589
4590//Get radio RDG enable setting
4591INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4592{
4593 if (NULL == output_bool)
4594 return RETURN_ERR;
4595 *output_bool = TRUE;
4596 return RETURN_OK;
4597}
4598
4599//Get radio RDG enable setting
4600INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4601{
4602 if (NULL == output_bool)
4603 return RETURN_ERR;
4604 *output_bool = TRUE;
4605 return RETURN_OK;
4606}
4607
4608//Set radio RDG enable setting
4609INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4610{
4611 return RETURN_ERR;
4612}
4613
4614//Get radio ADDBA enable setting
4615INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4616{
4617 if (NULL == output_bool)
4618 return RETURN_ERR;
4619 *output_bool = TRUE;
4620 return RETURN_OK;
4621}
4622
4623//Set radio ADDBA enable setting
4624INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4625{
4626 return RETURN_ERR;
4627}
4628
4629//Get radio auto block ack enable setting
4630INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4631{
4632 if (NULL == output_bool)
4633 return RETURN_ERR;
4634 *output_bool = TRUE;
4635 return RETURN_OK;
4636}
4637
4638//Set radio auto block ack enable setting
4639INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4640{
4641 return RETURN_ERR;
4642}
4643
4644//Get radio 11n pure mode enable support
4645INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4646{
4647 if (NULL == output_bool)
4648 return RETURN_ERR;
4649 *output_bool = TRUE;
4650 return RETURN_OK;
4651}
4652
4653//Get radio 11n pure mode enable setting
4654INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4655{
4656 if (NULL == output_bool)
4657 return RETURN_ERR;
4658 *output_bool = TRUE;
4659 return RETURN_OK;
4660}
4661
4662//Set radio 11n pure mode enable setting
4663INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4664{
4665 return RETURN_ERR;
4666}
4667
4668//Get radio IGMP snooping enable setting
4669INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4670{
developer81bf2ed2022-09-13 15:31:14 +08004671 char cmd[128]={0};
4672 char buf[4]={0};
4673 bool bridge = FALSE, mac80211 = FALSE;
4674 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4675
4676 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004677 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004678
4679 *output_bool = FALSE;
4680
4681 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4682 _syscmd(cmd, buf, sizeof(buf));
4683 if (strncmp(buf, "1", 1) == 0)
4684 bridge = TRUE;
4685
4686 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4687 _syscmd(cmd, buf, sizeof(buf));
4688 if (strncmp(buf, "1", 1) == 0)
4689 mac80211 = TRUE;
4690
4691 if (bridge && mac80211)
4692 *output_bool = TRUE;
4693
4694 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004695 return RETURN_OK;
4696}
4697
4698//Set radio IGMP snooping enable setting
4699INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4700{
developer81bf2ed2022-09-13 15:31:14 +08004701 char cmd[128]={0};
4702 char buf[4]={0};
4703
4704 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4705
4706 // bridge
4707 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4708 _syscmd(cmd, buf, sizeof(buf));
4709
4710 // mac80211
4711 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4712 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4713 _syscmd(cmd, buf, sizeof(buf));
4714 }
4715 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4716 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004717}
4718
4719//Get the Reset count of radio
4720INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4721{
4722 if (NULL == output_int)
4723 return RETURN_ERR;
4724 *output_int = (radioIndex==0)? 1: 3;
4725
4726 return RETURN_OK;
4727}
4728
4729
4730//---------------------------------------------------------------------------------------------------
4731//
4732// Additional Wifi AP level APIs used for Access Point devices
4733//
4734//---------------------------------------------------------------------------------------------------
4735
4736// creates a new ap and pushes these parameters to the hardware
4737INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4738{
4739 char buf[1024];
4740 char cmd[128];
4741
4742 if (NULL == essid)
4743 return RETURN_ERR;
4744
4745 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4746 _syscmd(cmd, buf, sizeof(buf));
4747
4748 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4749 _syscmd(cmd, buf, sizeof(buf));
4750
4751 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4752
4753 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4754 _syscmd(cmd, buf, sizeof(buf));
4755
4756 return RETURN_OK;
4757}
4758
4759// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4760INT wifi_deleteAp(INT apIndex)
4761{
4762 char buf[1024];
4763 char cmd[128];
4764
4765 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4766 _syscmd(cmd, buf, sizeof(buf));
4767
4768 wifi_removeApSecVaribles(apIndex);
4769
4770 return RETURN_OK;
4771}
4772
4773// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4774INT wifi_getApName(INT apIndex, CHAR *output_string)
4775{
4776 if(NULL == output_string)
4777 return RETURN_ERR;
4778
4779 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4780 return RETURN_OK;
4781}
4782
4783// Outputs the index number in that corresponds to the SSID string
4784INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4785{
4786 CHAR *pos = NULL;
4787
4788 *output_int = -1;
4789 pos = strstr(inputSsidString, AP_PREFIX);
4790 if(pos)
4791 {
4792 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4793 return RETURN_OK;
4794 }
4795 return RETURN_ERR;
4796}
4797
4798INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4799{
4800 return wifi_getIndexFromName(inputSsidString, output_int);
4801}
4802
4803// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4804INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4805{
4806 char buf[MAX_BUF_SIZE] = {0};
4807 char cmd[MAX_CMD_SIZE] = {0};
4808 char config_file[MAX_BUF_SIZE] = {0};
4809
4810 if(NULL == output_string)
4811 return RETURN_ERR;
4812
4813 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4814 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4815 if((strcmp(buf,"3")==0))
4816 snprintf(output_string, 32, "WPAand11i");
4817 else if((strcmp(buf,"2")==0))
4818 snprintf(output_string, 32, "11i");
4819 else if((strcmp(buf,"1")==0))
4820 snprintf(output_string, 32, "WPA");
4821 else
4822 snprintf(output_string, 32, "None");
4823
4824 return RETURN_OK;
4825}
4826
4827// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4828INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4829{
4830 char config_file[MAX_BUF_SIZE] = {0};
4831 struct params list;
4832
4833 if (NULL == beaconTypeString)
4834 return RETURN_ERR;
4835 list.name = "wpa";
4836 list.value = "0";
4837
4838 if((strcmp(beaconTypeString,"WPAand11i")==0))
4839 list.value="3";
4840 else if((strcmp(beaconTypeString,"11i")==0))
4841 list.value="2";
4842 else if((strcmp(beaconTypeString,"WPA")==0))
4843 list.value="1";
4844
4845 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4846 wifi_hostapdWrite(config_file, &list, 1);
4847 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4848 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4849 return RETURN_OK;
4850}
4851
4852// sets the beacon interval on the hardware for this AP
4853INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4854{
developer5f222492022-09-13 15:21:52 +08004855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4856 struct params params={'\0'};
4857 char buf[MAX_BUF_SIZE] = {'\0'};
4858 char config_file[MAX_BUF_SIZE] = {'\0'};
4859
4860 params.name = "beacon_int";
4861 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4862 params.value = buf;
4863
4864 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4865 wifi_hostapdWrite(config_file, &params, 1);
4866
4867 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4868 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4869 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004870}
4871
4872INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4873{
4874 //save config and apply instantly
4875 return RETURN_ERR;
4876}
4877
4878// Get the packet size threshold supported.
4879INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4880{
4881 //save config and apply instantly
4882 if (NULL == output_bool)
4883 return RETURN_ERR;
4884 *output_bool = FALSE;
4885 return RETURN_OK;
4886}
4887
4888// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4889INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4890{
4891 char cmd[128];
4892 char buf[512];
4893
4894 if (threshold > 0)
4895 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4896 else
4897 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4898 _syscmd(cmd, buf, sizeof(buf));
4899
4900 return RETURN_OK;
4901}
4902
4903// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4904INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4905{
4906 if (NULL == output_string)
4907 return RETURN_ERR;
4908 snprintf(output_string, 32, "TKIPandAESEncryption");
4909 return RETURN_OK;
4910
4911}
4912
4913// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4914INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4915{
4916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4917 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4918
4919 if(NULL == output_string)
4920 return RETURN_ERR;
4921
4922 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4923 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4924
4925 if(strcmp(buf,"0")==0)
4926 {
4927 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4928 snprintf(output_string, 32, "None");
4929 return RETURN_OK;
4930 }
4931 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4932 param_name = "rsn_pairwise";
4933 else if((strcmp(buf,"1")==0))
4934 param_name = "wpa_pairwise";
4935 else
4936 return RETURN_ERR;
4937 memset(output_string,'\0',32);
4938 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4939 wifi_hostapdRead(config_file,param_name,output_string,32);
4940 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4941
4942 if(strcmp(output_string,"TKIP") == 0)
4943 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4944 else if(strcmp(output_string,"CCMP") == 0)
4945 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4946 else if(strcmp(output_string,"TKIP CCMP") == 0)
4947 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4948
4949 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4950 return RETURN_OK;
4951}
4952
4953// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4954INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4955{
4956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4957 struct params params={'\0'};
4958 char output_string[32];
4959 char config_file[MAX_BUF_SIZE] = {0};
4960
4961 memset(output_string,'\0',32);
4962 wifi_getApWpaEncryptionMode(apIndex,output_string);
4963
4964 if(strcmp(encMode, "TKIPEncryption") == 0)
4965 params.value = "TKIP";
4966 else if(strcmp(encMode,"AESEncryption") == 0)
4967 params.value = "CCMP";
4968 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4969 params.value = "TKIP CCMP";
4970
4971 if((strcmp(output_string,"WPAand11i")==0))
4972 {
4973 params.name = "wpa_pairwise";
4974 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4975 wifi_hostapdWrite(config_file, &params, 1);
4976 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4977
4978 params.name,"rsn_pairwise";
4979 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4980 wifi_hostapdWrite(config_file, &params, 1);
4981 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4982
4983 return RETURN_OK;
4984 }
4985 else if((strcmp(output_string,"11i")==0))
4986 {
4987 params.name = "rsn_pairwise";
4988 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4989 wifi_hostapdWrite(config_file, &params, 1);
4990 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4991 return RETURN_OK;
4992 }
4993 else if((strcmp(output_string,"WPA")==0))
4994 {
4995 params.name = "wpa_pairwise";
4996 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4997 wifi_hostapdWrite(config_file, &params, 1);
4998 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4999 return RETURN_OK;
5000 }
5001
5002 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5003 return RETURN_OK;
5004}
5005
5006// deletes internal security varable settings for this ap
5007INT wifi_removeApSecVaribles(INT apIndex)
5008{
5009 //TODO: remove the entry in hostapd config file
5010 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5011 //_syscmd(cmd, buf, sizeof(buf));
5012
5013 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5014 //_syscmd(cmd, buf, sizeof(buf));
5015 return RETURN_ERR;
5016}
5017
5018// changes the hardware settings to disable encryption on this ap
5019INT wifi_disableApEncryption(INT apIndex)
5020{
5021 //Apply instantly
5022 return RETURN_ERR;
5023}
5024
5025// set the authorization mode on this ap
5026// mode mapping as: 1: open, 2: shared, 4:auto
5027INT wifi_setApAuthMode(INT apIndex, INT mode)
5028{
developeraf95c502022-09-13 16:18:22 +08005029 struct params params={0};
5030 char config_file[64] = {0};
5031 int ret;
5032
5033 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5034
5035 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5036 params.name = "auth_algs";
5037
5038 if (mode & 1 && mode & 2)
5039 params.value = "3";
5040 else if (mode & 2)
5041 params.value = "2";
5042 else if (mode & 1)
5043 params.value = "1";
5044 else
5045 params.value = "0";
5046
5047 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5048 wifi_hostapdWrite(config_file, &params, 1);
5049 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5050 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5051
5052 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005053}
5054
5055// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5056INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5057{
5058 //save to wifi config, and wait for wifi restart to apply
5059 struct params params={'\0'};
5060 char config_file[MAX_BUF_SIZE] = {0};
5061 int ret;
5062
5063 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5064 if(authMode == NULL)
5065 return RETURN_ERR;
5066
5067 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5068 params.name = "wpa_key_mgmt";
5069
5070 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5071 params.value = "WPA-PSK";
5072 else if(strcmp(authMode,"EAPAuthentication") == 0)
5073 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005074 else if (strcmp(authMode, "SAEAuthentication") == 0)
5075 params.value = "SAE";
5076 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5077 params.value = "WPA-EAP-SUITE-B-192";
developer06a01d92022-09-07 16:32:39 +08005078 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5079 return RETURN_OK; //This is taken careof in beaconType
5080
5081 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5082 ret=wifi_hostapdWrite(config_file,&params,1);
5083 if(!ret)
5084 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5085 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5086
5087 return ret;
5088}
5089
5090// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5091INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5092{
5093 //save to wifi config, and wait for wifi restart to apply
5094 char BeaconType[50] = {0};
5095 char config_file[MAX_BUF_SIZE] = {0};
5096
5097 *authMode = 0;
5098 wifi_getApBeaconType(apIndex,BeaconType);
5099 printf("%s____%s \n",__FUNCTION__,BeaconType);
5100
5101 if(strcmp(BeaconType,"None") == 0)
5102 strcpy(authMode,"None");
5103 else
5104 {
5105 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5106 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5107 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5108 if(strcmp(authMode,"WPA-PSK") == 0)
5109 strcpy(authMode,"SharedAuthentication");
5110 else if(strcmp(authMode,"WPA-EAP") == 0)
5111 strcpy(authMode,"EAPAuthentication");
5112 }
5113
5114 return RETURN_OK;
5115}
5116
5117// Outputs the number of stations associated per AP
5118INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5119{
5120 char cmd[128]={0};
5121 char buf[128]={0};
5122 BOOL status = false;
5123
5124 if(apIndex > MAX_APS)
5125 return RETURN_ERR;
5126
5127 wifi_getApEnable(apIndex,&status);
5128 if (!status)
5129 return RETURN_OK;
5130
5131 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5132 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5133 _syscmd(cmd, buf, sizeof(buf));
5134 sscanf(buf,"%lu", output_ulong);
5135
5136 return RETURN_OK;
5137}
5138
5139// manually removes any active wi-fi association with the device specified on this ap
5140INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5141{
5142 char buf[126]={'\0'};
5143
5144 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5145 system(buf);
5146
5147 return RETURN_OK;
5148}
5149
5150// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5151INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5152{
5153 if(NULL == output_int)
5154 return RETURN_ERR;
5155 *output_int = apIndex%2;
5156 return RETURN_OK;
5157}
5158
5159// sets the radio index for the specific ap
5160INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5161{
5162 //set to config only and wait for wifi reset to apply settings
5163 return RETURN_ERR;
5164}
5165
5166// Get the ACL MAC list per AP
5167INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5168{
5169 char cmd[MAX_CMD_SIZE]={'\0'};
5170 int ret = 0;
5171
5172 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5173 ret = _syscmd(cmd,macArray,buf_size);
5174 if (ret != 0)
5175 return RETURN_ERR;
5176
5177 return RETURN_OK;
5178}
5179
developere6aafda2022-09-13 14:59:28 +08005180INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5181{
5182 char cmd[MAX_CMD_SIZE]={'\0'};
5183 int ret = 0;
5184
5185 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5186 ret = _syscmd(cmd,macArray,buf_size);
5187 if (ret != 0)
5188 return RETURN_ERR;
5189
5190 return RETURN_OK;
5191}
5192
5193
developer06a01d92022-09-07 16:32:39 +08005194// Get the list of stations associated per AP
5195INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5196{
5197 char cmd[128];
5198
5199 if(apIndex > 3) //Currently supporting apIndex upto 3
5200 return RETURN_ERR;
5201 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5202 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5203 _syscmd(cmd, macArray, buf_size);
5204
5205 return RETURN_OK;
5206}
5207
5208// adds the mac address to the filter list
5209//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5210INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5211{
5212 char cmd[MAX_CMD_SIZE]={'\0'};
5213 char buf[MAX_BUF_SIZE]={'\0'};
5214
5215#if 0
5216 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5217 if(_syscmd(cmd,buf,sizeof(buf)))
5218 return RETURN_ERR;
5219#endif
5220 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5221 if(_syscmd(cmd,buf,sizeof(buf)))
5222 return RETURN_ERR;
5223
5224 return RETURN_OK;
5225}
5226
5227// deletes the mac address from the filter list
5228//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5229INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5230{
5231 char cmd[MAX_CMD_SIZE]={'\0'};
5232 char buf[MAX_BUF_SIZE]={'\0'};
5233
5234#if 0
5235 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5236 if(_syscmd(cmd,buf,sizeof(buf)))
5237 return RETURN_ERR;
5238
5239#endif
5240 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5241 if(_syscmd(cmd,buf,sizeof(buf)))
5242 return RETURN_ERR;
5243
5244 return RETURN_OK;
5245}
5246
5247// outputs the number of devices in the filter list
5248INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5249{
developere6aafda2022-09-13 14:59:28 +08005250 char cmd[MAX_BUF_SIZE]={0};
5251 char buf[MAX_CMD_SIZE]={0};
5252
5253 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5254 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005255 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005256
5257 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5258 _syscmd(cmd, buf, sizeof(buf));
5259
5260 *output_uint = atoi(buf);
5261
5262 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5263 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005264}
5265
5266INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5267{
5268 char cmd[128]={'\0'};
5269 char buf[128]={'\0'};
5270
5271 if(strcmp(action,"DENY")==0)
5272 {
5273 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5274 system(buf);
5275 return RETURN_OK;
5276 }
5277
5278 if(strcmp(action,"ALLOW")==0)
5279 {
5280 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5281 system(buf);
5282 return RETURN_OK;
5283 }
5284
5285 return RETURN_ERR;
5286
5287}
5288
5289// enable kick for devices on acl black list
5290INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5291{
5292 char aclArray[512] = {0}, *acl = NULL;
5293 char assocArray[512] = {0}, *asso = NULL;
5294
developere6aafda2022-09-13 14:59:28 +08005295 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005296 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5297
5298 // if there are no devices connected there is nothing to do
5299 if (strlen(assocArray) < 17)
5300 return RETURN_OK;
5301
5302 if (enable == TRUE)
5303 {
5304 //kick off the MAC which is in ACL array (deny list)
5305 acl = strtok(aclArray, "\r\n");
5306 while (acl != NULL) {
5307 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5308 wifi_kickApAssociatedDevice(apIndex, acl);
5309
5310 acl = strtok(NULL, "\r\n");
5311 }
developere6aafda2022-09-13 14:59:28 +08005312 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005313 }
5314 else
5315 {
developere6aafda2022-09-13 14:59:28 +08005316 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005317 }
5318
5319#if 0
5320 //TODO: need to revisit below implementation
5321 char aclArray[512]={0}, *acl=NULL;
5322 char assocArray[512]={0}, *asso=NULL;
5323 char buf[256]={'\0'};
5324 char action[10]={'\0'};
5325 FILE *fr=NULL;
5326 char interface[10]={'\0'};
5327 char config_file[MAX_BUF_SIZE] = {0};
5328
5329 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5330 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5331 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5332 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5333
5334 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5335 system(buf);
5336 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5337 system(buf);
5338 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5339 system(buf);
5340 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5341 system(buf);
5342 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5343 system(buf);
5344
5345 if ( enable == TRUE )
5346 {
5347 int device_count=0;
5348 strcpy(action,"DENY");
5349 //kick off the MAC which is in ACL array (deny list)
5350 acl = strtok (aclArray,",");
5351 while (acl != NULL) {
5352 if(strlen(acl)>=17)
5353 {
5354 apply_rules(apIndex, acl,action,interface);
5355 device_count++;
5356 //Register mac to be blocked ,in syscfg.db persistent storage
5357 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5358 system(buf);
5359 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5360 system(buf);
5361 system("syscfg commit");
5362
5363 wifi_kickApAssociatedDevice(apIndex, acl);
5364 }
5365 acl = strtok (NULL, ",");
5366 }
5367 }
5368 else
5369 {
5370 int device_count=0;
5371 char cmdmac[20]={'\0'};
5372 strcpy(action,"ALLOW");
5373 //kick off the MAC which is not in ACL array (allow list)
5374 acl = strtok (aclArray,",");
5375 while (acl != NULL) {
5376 if(strlen(acl)>=17)
5377 {
5378 apply_rules(apIndex, acl,action,interface);
5379 device_count++;
5380 //Register mac to be Allowed ,in syscfg.db persistent storage
5381 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5382 system(buf);
5383 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5384 system(buf);
5385 sprintf(cmdmac,"%s",acl);
5386 }
5387 acl = strtok (NULL, ",");
5388 }
5389 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5390 system(buf);
5391
5392 //Disconnect the mac which is not in ACL
5393 asso = strtok (assocArray,",");
5394 while (asso != NULL) {
5395 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5396 wifi_kickApAssociatedDevice(apIndex, asso);
5397 asso = strtok (NULL, ",");
5398 }
5399 }
5400#endif
5401 return RETURN_OK;
5402}
5403
5404INT wifi_setPreferPrivateConnection(BOOL enable)
5405{
5406 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5407 char buf[1024] = {0};
5408
5409 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5410 if(enable == TRUE)
5411 {
5412 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5413 sprintf(buf,"ifconfig %s down" ,interface_name);
5414 system(buf);
5415 memset(buf,0,sizeof(buf));
5416 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5417 sprintf(buf,"ifconfig %s down" ,interface_name);
5418 system(buf);
5419 }
5420 else
5421 {
5422 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5423 if(strcmp(ssid_cur_value,"1") == 0)
5424 wifi_RestartPrivateWifi_5G();
5425 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5426 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5427 if(strcmp(ssid_cur_value,"1") == 0)
5428 wifi_RestartHostapd_2G();
5429 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5430 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5431 if(strcmp(ssid_cur_value,"1") == 0)
5432 wifi_RestartHostapd_5G();
5433 }
5434 return RETURN_OK;
5435}
5436
5437// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5438INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5439{
5440 int items = 1;
5441 struct params list[2];
5442 char buf[MAX_BUF_SIZE] = {0};
5443 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005444 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005445
5446 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005447
developer10adcc12022-09-13 14:39:17 +08005448 if (filterMode == 0) {
5449 sprintf(buf, "%d", 0);
5450 list[0].value = buf;
5451
5452 char cmd[128], rtn[128];
5453 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5454 _syscmd(cmd, rtn, sizeof(rtn));
5455 memset(cmd,0,sizeof(cmd));
5456 // Delete deny_mac_file in hostapd configuration
5457 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5458 _syscmd(cmd, rtn, sizeof(rtn));
5459 }
5460 else if (filterMode == 1) {
5461 sprintf(buf, "%d", filterMode);
5462 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005463 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5464 list[1].name = "accept_mac_file";
5465 list[1].value = acl_file;
5466 items = 2;
developer10adcc12022-09-13 14:39:17 +08005467 } else if (filterMode == 2) {
5468 //TODO: deny_mac_file
5469 sprintf(buf, "%d", 0);
5470 list[0].value = buf;
5471 list[1].name = "deny_mac_file";
5472 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5473 list[1].value = deny_file;
5474 items = 2;
5475 } else {
5476 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005477 }
developer10adcc12022-09-13 14:39:17 +08005478
developer06a01d92022-09-07 16:32:39 +08005479 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5480 wifi_hostapdWrite(config_file, list, items);
5481
5482 return RETURN_OK;
5483
5484#if 0
5485 if(apIndex==0 || apIndex==1)
5486 {
5487 //set the filtermode
5488 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5489 system(buf);
5490 system("syscfg commit");
5491
5492 if(filterMode==0)
5493 {
5494 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5495 system(buf);
5496 return RETURN_OK;
5497 }
5498 }
5499 return RETURN_OK;
5500#endif
5501}
5502
5503// 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.
5504INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5505{
5506 return RETURN_ERR;
5507}
5508
5509// gets the vlan ID for this ap from an internal enviornment variable
5510INT wifi_getApVlanID(INT apIndex, INT *output_int)
5511{
5512 if(apIndex=0)
5513 {
5514 *output_int=100;
5515 return RETURN_OK;
5516 }
5517
5518 return RETURN_ERR;
5519}
5520
5521// sets the vlan ID for this ap to an internal enviornment variable
5522INT wifi_setApVlanID(INT apIndex, INT vlanId)
5523{
5524 //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)
5525 return RETURN_ERR;
5526}
5527
5528// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5529INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5530{
5531 snprintf(bridgeName, 32, "brlan0");
5532 snprintf(IP, 32, "10.0.0.1");
5533 snprintf(subnet, 32, "255.255.255.0");
5534
5535 return RETURN_OK;
5536}
5537
5538//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5539INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5540{
5541 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5542 return RETURN_ERR;
5543}
5544
5545// reset the vlan configuration for this ap
5546INT wifi_resetApVlanCfg(INT apIndex)
5547{
developerf5fef612022-09-20 19:38:26 +08005548 char original_config_file[64] = {0};
5549 char current_config_file[64] = {0};
5550 char buf[64] = {0};
5551 char cmd[64] = {0};
5552 char vlan_file[64] = {0};
5553 char vlan_tagged_interface[16] = {0};
5554 char vlan_bridge[16] = {0};
5555 char vlan_naming[16] = {0};
5556 struct params list[4] = {0};
5557 wifi_band band;
5558
5559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5560
5561 band = wifi_index_to_band(apIndex);
5562 if (band == band_2_4)
5563 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5564 else if (band = band_5)
5565 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5566 else if (band = band_6)
5567 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5568
5569 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5570
5571 if (strlen(vlan_file) == 0)
5572 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005573
developerf5fef612022-09-20 19:38:26 +08005574 // The file should exist or this vap would not work.
5575 if (access(vlan_file, F_OK) != 0) {
5576 sprintf(cmd, "touch %s", vlan_file);
5577 _syscmd(cmd, buf, sizeof(buf));
5578 }
5579 list[0].name = "vlan_file";
5580 list[0].value = vlan_file;
5581
5582 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5583 list[1].name = "vlan_tagged_interface";
5584 list[1].value = vlan_tagged_interface;
5585
5586 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5587 list[2].name = "vlan_bridge";
5588 list[2].value = vlan_bridge;
5589
5590 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5591 list[3].name = "vlan_naming";
5592 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005593
developerf5fef612022-09-20 19:38:26 +08005594 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5595 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005596 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005597 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005598
developerf5fef612022-09-20 19:38:26 +08005599 // restart this ap
5600 wifi_setApEnable(apIndex, FALSE);
5601 wifi_setApEnable(apIndex, TRUE);
5602
5603 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5604
5605 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005606}
5607
5608// 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.
5609INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5610{
5611 return RETURN_ERR;
5612}
5613
5614// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5615INT wifi_startHostApd()
5616{
5617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5618 system("systemctl start hostapd.service");
5619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5620 return RETURN_OK;
5621 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5622}
5623
5624// stops hostapd
5625INT wifi_stopHostApd()
5626{
5627 char cmd[128] = {0};
5628 char buf[128] = {0};
5629
5630 sprintf(cmd,"systemctl stop hostapd");
5631 _syscmd(cmd, buf, sizeof(buf));
5632
5633 return RETURN_OK;
5634}
5635
5636// restart hostapd dummy function
5637INT wifi_restartHostApd()
5638{
5639 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5640 system("systemctl restart hostapd-global");
5641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5642
5643 return RETURN_OK;
5644}
5645
5646static int align_hostapd_config(int index)
5647{
5648 ULONG lval;
5649 wifi_getRadioChannel(index%2, &lval);
5650 wifi_setRadioChannel(index%2, lval);
5651}
5652
5653// sets the AP enable status variable for the specified ap.
5654INT wifi_setApEnable(INT apIndex, BOOL enable)
5655{
5656 char config_file[MAX_BUF_SIZE] = {0};
5657 char cmd[MAX_CMD_SIZE] = {0};
5658 char buf[MAX_BUF_SIZE] = {0};
5659 BOOL status;
5660
5661 wifi_getApEnable(apIndex,&status);
5662 if (enable == status)
5663 return RETURN_OK;
5664
5665 if (enable == TRUE) {
5666 int radioIndex = apIndex % NUMBER_OF_RADIOS;
developer06a01d92022-09-07 16:32:39 +08005667 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5668 //Hostapd will bring up this interface
5669 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5670 _syscmd(cmd, buf, sizeof(buf));
5671 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5672 _syscmd(cmd, buf, sizeof(buf));
5673 }
5674 else {
5675 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5676 _syscmd(cmd, buf, sizeof(buf));
5677 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5678 _syscmd(cmd, buf, sizeof(buf));
5679 }
5680 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5681 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5682 _syscmd(cmd, buf, sizeof(buf));
5683 //Wait for wifi up/down to apply
5684 return RETURN_OK;
5685}
5686
5687// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5688INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5689{
5690 char cmd[MAX_CMD_SIZE] = {'\0'};
5691 char buf[MAX_BUF_SIZE] = {'\0'};
5692
5693 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5694 return RETURN_ERR;
5695
5696 *output_bool = 0;
5697
5698 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5699 {
developer70490032022-09-13 15:45:20 +08005700 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005701 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5702 }
5703
5704 return RETURN_OK;
5705}
5706
5707// Outputs the AP "Enabled" "Disabled" status from driver
5708INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5709{
5710 char cmd[128] = {0};
5711 char buf[128] = {0};
5712 BOOL output_bool;
5713
5714 if ( NULL == output_string)
5715 return RETURN_ERR;
5716 wifi_getApEnable(apIndex,&output_bool);
5717
5718 if(output_bool == 1)
5719 snprintf(output_string, 32, "Up");
5720 else
5721 snprintf(output_string, 32, "Disable");
5722
5723 return RETURN_OK;
5724}
5725
5726//Indicates whether or not beacons include the SSID name.
5727// outputs a 1 if SSID on the AP is enabled, else outputs 0
5728INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5729{
5730 //get the running status
5731 char config_file[MAX_BUF_SIZE] = {0};
5732 char buf[16] = {0};
5733
5734 if (!output)
5735 return RETURN_ERR;
5736
5737 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5738 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5739 *output = (strncmp("0",buf,1) == 0);
5740
5741 return RETURN_OK;
5742}
5743
5744// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5745INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5746{
5747 //store the config, apply instantly
5748 char config_file[MAX_BUF_SIZE] = {0};
5749 struct params list;
5750
5751 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5752 list.name = "ignore_broadcast_ssid";
5753 list.value = enable?"0":"1";
5754
5755 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5756 wifi_hostapdWrite(config_file, &list, 1);
5757 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5758 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005759 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005760 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5761
5762 return RETURN_OK;
5763}
5764
5765//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5766INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5767{
5768 //get the running status
5769 if(!output_uint)
5770 return RETURN_ERR;
5771 *output_uint=16;
5772 return RETURN_OK;
5773}
5774
5775INT wifi_setApRetryLimit(INT apIndex, UINT number)
5776{
5777 //apply instantly
5778 return RETURN_ERR;
5779}
5780
5781//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5782INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5783{
5784 if(!output)
5785 return RETURN_ERR;
5786 *output=TRUE;
5787 return RETURN_OK;
5788}
5789
5790//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5791INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5792{
5793 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005794 char cmd[128] = {0};
5795 char buf[128] = {0};
5796 int max_radio_num = 0, radioIndex = 0;
developer3ab38042022-09-13 14:17:03 +08005797
developer0b246d12022-09-30 15:24:20 +08005798 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005799
developer0b246d12022-09-30 15:24:20 +08005800 wifi_getMaxRadioNumber(&max_radio_num);
5801 radioIndex = apIndex % max_radio_num;
5802 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", radioIndex);
5803 _syscmd(cmd,buf, sizeof(buf));
5804
5805 if (strlen(buf) > 0)
5806 *output = true;
5807
5808 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005809
developer06a01d92022-09-07 16:32:39 +08005810 return RETURN_OK;
5811}
5812
5813//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5814INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5815{
5816 //get the running status from driver
5817 if(!output)
5818 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005819
5820 char config_file[MAX_BUF_SIZE] = {0};
5821 char buf[16] = {0};
5822
5823 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5824 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5825 if (strncmp("1",buf,1) == 0)
5826 *output = TRUE;
5827 else
5828 *output = FALSE;
5829
developer06a01d92022-09-07 16:32:39 +08005830 return RETURN_OK;
5831}
5832
5833// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5834INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5835{
5836 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005837 char config_file[MAX_BUF_SIZE] = {0};
5838 struct params list;
5839
5840 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5841 list.name = "wmm_enabled";
5842 list.value = enable?"1":"0";
5843
5844 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5845 wifi_hostapdWrite(config_file, &list, 1);
5846 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5847 wifi_reloadAp(apIndex);
5848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5849
5850 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005851}
5852
5853//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.
5854INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5855{
5856 //get the running status from driver
5857 if(!output)
5858 return RETURN_ERR;
5859 *output=TRUE;
5860 return RETURN_OK;
5861}
5862
5863// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5864INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5865{
5866 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005867 char config_file[MAX_BUF_SIZE] = {0};
5868 struct params list;
5869
5870 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5871 list.name = "uapsd_advertisement_enabled";
5872 list.value = enable?"1":"0";
5873
5874 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5875 wifi_hostapdWrite(config_file, &list, 1);
5876 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5877 wifi_reloadAp(apIndex);
5878 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5879
5880 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005881}
5882
developer6daeb3f2022-09-30 13:36:39 +08005883// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005884INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5885{
developer6daeb3f2022-09-30 13:36:39 +08005886 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5887 char cmd[128] = {0};
5888 char buf[128] = {0};
5889 char ack_filepath[128] = {0};
5890 uint16_t bitmap = 0;
5891 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5892 FILE *f = NULL;
5893
5894 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5895
5896 // Get current setting
5897 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
5898 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
5899 _syscmd(cmd, buf, sizeof(buf));
5900 if (strlen(buf) > 0)
5901 bitmap = strtoul(buf, NULL, 10);
5902
5903 bitmap = strtoul(buf, NULL, 10);
5904
5905 if (ackPolicy == TRUE) { // True, unset this class
5906 bitmap &= ~class_map[class];
5907 } else { // False, set this class
5908 bitmap |= class_map[class];
5909 }
5910
5911 f = fopen(ack_filepath, "w");
5912 if (f == NULL) {
5913 fprintf(stderr, "%s: fopen failed\n", __func__);
5914 return RETURN_ERR;
5915 }
5916 fprintf(f, "%hu", bitmap);
5917 fclose(f);
5918
5919 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
5920 _syscmd(cmd, buf, sizeof(buf));
5921
5922 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5923 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005924}
5925
5926//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.
5927INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5928{
5929 //get the running status from driver
5930 if(!output_uint)
5931 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005932
5933 char output[16]={'\0'};
5934 char config_file[MAX_BUF_SIZE] = {0};
5935
5936 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5937 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5938 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5939 else {
5940 int device_num = atoi(output);
5941 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5942 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5943 return RETURN_ERR;
5944 }
5945 else {
5946 *output_uint = device_num;
5947 }
5948 }
5949
developer06a01d92022-09-07 16:32:39 +08005950 return RETURN_OK;
5951}
5952
5953INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5954{
5955 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005956 char str[MAX_BUF_SIZE]={'\0'};
5957 char cmd[MAX_CMD_SIZE]={'\0'};
5958 struct params params;
5959 char config_file[MAX_BUF_SIZE] = {0};
5960
5961 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5962 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5963 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5964 return RETURN_ERR;
5965 }
5966 sprintf(str, "%d", number);
5967 params.name = "max_num_sta";
5968 params.value = str;
5969
5970 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5971 int ret = wifi_hostapdWrite(config_file, &params, 1);
5972 if (ret) {
5973 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5974 ,__func__, ret);
5975 }
5976
5977 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5978 if (ret) {
5979 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5980 ,__func__, ret);
5981 }
5982 wifi_reloadAp(apIndex);
5983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5984
5985 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005986}
5987
5988//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.
5989INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5990{
5991 //get the current threshold
5992 if(!output_uint)
5993 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005994 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5995 if (*output_uint == 0)
5996 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08005997 return RETURN_OK;
5998}
5999
6000INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6001{
6002 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006003 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6004 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006005 return RETURN_ERR;
6006}
6007
6008//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.
6009INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6010{
6011 if(!output_uint)
6012 return RETURN_ERR;
6013 *output_uint = 3;
6014 return RETURN_OK;
6015}
6016
6017//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6018INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6019{
6020 if(!output_uint)
6021 return RETURN_ERR;
6022 *output_uint = 3;
6023 return RETURN_OK;
6024}
6025
6026//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.
6027INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6028{
6029 if(!output_in_seconds)
6030 return RETURN_ERR;
6031 *output_in_seconds = 0;
6032 return RETURN_OK;
6033}
6034
6035//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
6036INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6037{
6038 if(!output || apIndex>=MAX_APS)
6039 return RETURN_ERR;
6040 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006041 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006042 return RETURN_OK;
6043}
6044
6045//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6046INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6047{
developer587c1b62022-09-27 15:58:59 +08006048 char config_file[128] = {0};
6049 char wpa[16] = {0};
6050 char key_mgmt[64] = {0};
6051 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006052 if (!output)
6053 return RETURN_ERR;
6054
6055 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006056 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006057
developer587c1b62022-09-27 15:58:59 +08006058 strcpy(output, "None");//Copying "None" to output string for default case
6059 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6060 if (strstr(key_mgmt, "WPA-PSK")) {
developer517a9792022-10-05 19:37:42 +08006061 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006062 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006063 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006064 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006065 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006066 snprintf(output, 32, "WPA-WPA2-Personal");
6067
6068 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006069 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006070 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006071 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006072 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006073 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006074 snprintf(output, 32, "WPA-WPA2-Enterprise");
6075 } else if (strstr(key_mgmt, "SAE")) {
6076 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
6077 int disable = strtol(buf, NULL, 16);
6078 if (disable & 0x1)
6079 snprintf(output, 32, "WPA3-Personal");
6080 else
6081 snprintf(output, 32, "WPA3-Transition");
6082 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6083 snprintf(output, 32, "WPA3-Enterprise");
6084 }
developer06a01d92022-09-07 16:32:39 +08006085
6086 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6087 return RETURN_OK;
6088#if 0
6089 //TODO: need to revisit below implementation
6090 char securityType[32], authMode[32];
6091 int enterpriseMode=0;
6092
6093 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6094 if(!output)
6095 return RETURN_ERR;
6096
6097 wifi_getApBeaconType(apIndex, securityType);
6098 strcpy(output,"None");//By default, copying "None" to output string
6099 if (strncmp(securityType,"None", strlen("None")) == 0)
6100 return RETURN_OK;
6101
6102 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6103 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6104
6105 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6106 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6107 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6108 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6109 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6110 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6111 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6112
6113 return RETURN_OK;
6114#endif
6115}
6116
6117INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6118{
6119 char securityType[32];
6120 char authMode[32];
6121
6122 //store settings and wait for wifi up to apply
6123 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6124 if(!encMode)
6125 return RETURN_ERR;
6126
developer06a01d92022-09-07 16:32:39 +08006127 if (strcmp(encMode, "None")==0)
6128 {
6129 strcpy(securityType,"None");
6130 strcpy(authMode,"None");
6131 }
6132 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6133 {
6134 strcpy(securityType,"WPAand11i");
6135 strcpy(authMode,"PSKAuthentication");
6136 }
6137 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6138 {
6139 strcpy(securityType,"WPAand11i");
6140 strcpy(authMode,"EAPAuthentication");
6141 }
6142 else if (strcmp(encMode, "WPA-Personal")==0)
6143 {
6144 strcpy(securityType,"WPA");
6145 strcpy(authMode,"PSKAuthentication");
6146 }
6147 else if (strcmp(encMode, "WPA-Enterprise")==0)
6148 {
6149 strcpy(securityType,"WPA");
6150 strcpy(authMode,"EAPAuthentication");
6151 }
6152 else if (strcmp(encMode, "WPA2-Personal")==0)
6153 {
6154 strcpy(securityType,"11i");
6155 strcpy(authMode,"PSKAuthentication");
6156 }
6157 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6158 {
6159 strcpy(securityType,"11i");
6160 strcpy(authMode,"EAPAuthentication");
6161 }
developer587c1b62022-09-27 15:58:59 +08006162 else if (strcmp(encMode, "WPA3-Personal") == 0)
6163 {
6164 strcpy(securityType,"11i");
6165 strcpy(authMode,"SAEAuthentication");
6166 }
6167 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6168 {
6169 strcpy(securityType,"11i");
6170 strcpy(authMode,"EAP_192-bit_Authentication");
6171 }
developer06a01d92022-09-07 16:32:39 +08006172 else
6173 {
6174 strcpy(securityType,"None");
6175 strcpy(authMode,"None");
6176 }
6177 wifi_setApBeaconType(apIndex, securityType);
6178 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6179 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6180
6181 return RETURN_OK;
6182}
6183
6184
6185//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6186// output_string must be pre-allocated as 64 character string by caller
6187// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6188INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6189{
6190 char buf[16];
6191 char config_file[MAX_BUF_SIZE] = {0};
6192
6193 if(output_string==NULL)
6194 return RETURN_ERR;
6195
6196 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6197 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6198
6199 if(strcmp(buf,"0")==0)
6200 {
6201 printf("wpa_mode is %s ......... \n",buf);
6202 return RETURN_ERR;
6203 }
6204
6205 wifi_dbg_printf("\nFunc=%s\n",__func__);
6206 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6207 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6208 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6209
6210 return RETURN_OK;
6211}
6212
6213// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6214// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6215INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6216{
6217 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6218 struct params params={'\0'};
6219 int ret;
6220 char config_file[MAX_BUF_SIZE] = {0};
6221
6222 if(NULL == preSharedKey)
6223 return RETURN_ERR;
6224
6225 params.name = "wpa_passphrase";
6226
6227 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6228 {
6229 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6230 return RETURN_ERR;
6231 }
6232 params.value = preSharedKey;
6233 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6234 ret = wifi_hostapdWrite(config_file, &params, 1);
6235 if(!ret)
6236 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6237 return ret;
6238 //TODO: call hostapd_cli for dynamic_config_control
6239}
6240
6241//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6242// outputs the passphrase, maximum 63 characters
6243INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6244{
6245 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6246
6247 wifi_dbg_printf("\nFunc=%s\n",__func__);
6248 if (NULL == output_string)
6249 return RETURN_ERR;
6250
6251 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6252 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6253 if(strcmp(buf,"0")==0)
6254 {
6255 printf("wpa_mode is %s ......... \n",buf);
6256 return RETURN_ERR;
6257 }
6258
6259 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6260 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6261
6262 return RETURN_OK;
6263}
6264
6265// sets the passphrase enviornment variable, max 63 characters
6266INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6267{
6268 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6269 struct params params={'\0'};
6270 char config_file[MAX_BUF_SIZE] = {0};
6271 int ret;
6272
6273 if(NULL == passPhrase)
6274 return RETURN_ERR;
6275
6276 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6277 {
6278 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6279 return RETURN_ERR;
6280 }
6281 params.name = "wpa_passphrase";
6282 params.value = passPhrase;
6283 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6284 ret=wifi_hostapdWrite(config_file,&params,1);
6285 if(!ret)
6286 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6287
6288 return ret;
6289}
6290
6291//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.
6292INT wifi_setApSecurityReset(INT apIndex)
6293{
developer8d583982022-09-20 11:28:22 +08006294 char original_config_file[64] = {0};
6295 char current_config_file[64] = {0};
6296 char buf[64] = {0};
6297 char cmd[64] = {0};
6298 char wpa[4] = {0};
6299 char wpa_psk[64] = {0};
6300 char wpa_passphrase[64] = {0};
6301 char wpa_psk_file[128] = {0};
6302 char wpa_key_mgmt[64] = {0};
6303 char wpa_pairwise[32] = {0};
6304 wifi_band band;
6305 struct params list[6];
6306
6307 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6308
6309 band = wifi_index_to_band(apIndex);
6310 if (band == band_2_4)
6311 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6312 else if (band = band_5)
6313 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6314 else if (band = band_6)
6315 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6316 else
6317 return RETURN_ERR;
6318
6319 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6320 list[0].name = "wpa";
6321 list[0].value = wpa;
6322
6323 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6324 list[1].name = "wpa_psk";
6325 list[1].value = wpa_psk;
6326
6327 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6328 list[2].name = "wpa_passphrase";
6329 list[2].value = wpa_passphrase;
6330
6331 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6332
6333 if (strlen(wpa_psk_file) == 0)
6334 strcpy(wpa_psk_file, PSK_FILE);
6335
6336 if (access(wpa_psk_file, F_OK) != 0) {
6337 sprintf(cmd, "touch %s", wpa_psk_file);
6338 _syscmd(cmd, buf, sizeof(buf));
6339 }
6340 list[3].name = "wpa_psk_file";
6341 list[3].value = wpa_psk_file;
6342
6343 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6344 list[4].name = "wpa_key_mgmt";
6345 list[4].value = wpa_key_mgmt;
6346
6347 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6348 list[5].name = "wpa_pairwise";
6349 list[5].value = wpa_pairwise;
6350
6351 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6352 wifi_hostapdWrite(current_config_file, list, 6);
6353
6354 wifi_setApEnable(apIndex, FALSE);
6355 wifi_setApEnable(apIndex, TRUE);
6356
6357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6358 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006359}
6360
6361//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).
6362INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6363{
developer8f2ddd52022-09-13 15:39:24 +08006364 char config_file[64] = {0};
6365 char buf[64] = {0};
6366 char cmd[256] = {0};
6367
6368 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6369
developer06a01d92022-09-07 16:32:39 +08006370 if(!IP_output || !Port_output || !RadiusSecret_output)
6371 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006372
developer8f2ddd52022-09-13 15:39:24 +08006373 // Read the first matched config
6374 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6375 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6376 _syscmd(cmd, buf, sizeof(buf));
6377 strncpy(IP_output, buf, 64);
6378
6379 memset(buf, 0, sizeof(buf));
6380 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6381 _syscmd(cmd, buf, sizeof(buf));
6382 *Port_output = atoi(buf);
6383
6384 memset(buf, 0, sizeof(buf));
6385 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6386 _syscmd(cmd, buf, sizeof(buf));
6387 strncpy(RadiusSecret_output, buf, 64);
6388
6389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006390 return RETURN_OK;
6391}
6392
6393INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6394{
developer8f2ddd52022-09-13 15:39:24 +08006395 char config_file[64] = {0};
6396 char port_str[8] = {0};
6397 char cmd[256] = {0};
6398 char buf[128] = {0};
6399
6400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6401
6402 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6403
6404 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6405 _syscmd(cmd, buf, sizeof(buf));
6406 memset(cmd, 0, sizeof(cmd));
6407
6408 snprintf(port_str, sizeof(port_str), "%d", port);
6409 if (strlen(buf) == 0)
6410 // Append
6411 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6412 "auth_server_addr=%s\\n"
6413 "auth_server_port=%s\\n"
6414 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6415 else {
6416 // Delete the three lines setting after the "# radius 1" comment
6417 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6418 _syscmd(cmd, buf, sizeof(buf));
6419 memset(cmd, 0, sizeof(cmd));
6420 // Use "# radius 1" comment to find the location to insert the radius setting
6421 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6422 "# radius 1\\n"
6423 "auth_server_addr=%s\\n"
6424 "auth_server_port=%s\\n"
6425 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6426 }
6427 if(_syscmd(cmd, buf, sizeof(buf))) {
6428 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6429 return RETURN_ERR;
6430 }
6431
6432 wifi_reloadAp(apIndex);
6433 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6434 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006435}
6436
6437INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6438{
developer8f2ddd52022-09-13 15:39:24 +08006439 char config_file[64] = {0};
6440 char buf[64] = {0};
6441 char cmd[256] = {0};
6442
6443 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6444
developer06a01d92022-09-07 16:32:39 +08006445 if(!IP_output || !Port_output || !RadiusSecret_output)
6446 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006447
6448 // Read the second matched config
6449 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6450 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6451 _syscmd(cmd, buf, sizeof(buf));
6452 strncpy(IP_output, buf, 64);
6453
6454 memset(buf, 0, sizeof(buf));
6455 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6456 _syscmd(cmd, buf, sizeof(buf));
6457 *Port_output = atoi(buf);
6458
6459 memset(buf, 0, sizeof(buf));
6460 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6461 _syscmd(cmd, buf, sizeof(buf));
6462 strncpy(RadiusSecret_output, buf, 64);
6463
6464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006465 return RETURN_OK;
6466}
6467
6468INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6469{
developer8f2ddd52022-09-13 15:39:24 +08006470 char config_file[64] = {0};
6471 char port_str[8] = {0};
6472 char cmd[256] = {0};
6473 char buf[128] = {0};
6474
6475 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6476
6477 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6478
6479 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6480 _syscmd(cmd, buf, sizeof(buf));
6481 memset(cmd, 0, sizeof(cmd));
6482
6483 snprintf(port_str, sizeof(port_str), "%d", port);
6484 if (strlen(buf) == 0)
6485 // Append
6486 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6487 "auth_server_addr=%s\\n"
6488 "auth_server_port=%s\\n"
6489 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6490 else {
6491 // Delete the three lines setting after the "# radius 2" comment
6492 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6493 _syscmd(cmd, buf, sizeof(buf));
6494 memset(cmd, 0, sizeof(cmd));
6495 // Use "# radius 2" comment to find the location to insert the radius setting
6496 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6497 "# radius 2\\n"
6498 "auth_server_addr=%s\\n"
6499 "auth_server_port=%s\\n"
6500 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6501 }
6502 if(_syscmd(cmd, buf, sizeof(buf))) {
6503 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6504 return RETURN_ERR;
6505 }
6506
6507 wifi_reloadAp(apIndex);
6508 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6509 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006510}
6511
6512//RadiusSettings
6513INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6514{
6515 if(!output)
6516 return RETURN_ERR;
6517
6518 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6519 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6520 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6521 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6522 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6523 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.
6524 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6525 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6526 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6527 //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.
6528
6529 return RETURN_OK;
6530}
6531
6532INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6533{
6534 //store the paramters, and apply instantly
6535 return RETURN_ERR;
6536}
6537
6538//Device.WiFi.AccessPoint.{i}.WPS.Enable
6539//Enables or disables WPS functionality for this access point.
6540// outputs the WPS enable state of this ap in output_bool
6541INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6542{
6543 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6544 if(!output_bool || !(apIndex==0 || apIndex==1))
6545 return RETURN_ERR;
6546 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6547 _syscmd(cmd, buf, sizeof(buf));
6548 if(strstr(buf, "configured"))
6549 *output_bool=TRUE;
6550 else
6551 *output_bool=FALSE;
6552
6553 return RETURN_OK;
6554}
6555
6556//Device.WiFi.AccessPoint.{i}.WPS.Enable
6557// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6558INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6559{
6560 char config_file[MAX_BUF_SIZE] = {0};
6561 struct params params;
6562
6563 if(!(apIndex==0 || apIndex==1))
6564 return RETURN_ERR;
6565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6566 //store the paramters, and wait for wifi up to apply
6567 params.name = "wps_state";
6568 params.value = enable ? "2":"0";
6569
6570 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6571 wifi_hostapdWrite(config_file, &params, 1);
6572 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6573 wifi_reloadAp(apIndex);
6574
6575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6576 return RETURN_OK;
6577}
6578
6579//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
6580INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6581{
6582 if(!output)
6583 return RETURN_ERR;
6584 snprintf(output, 128, "PushButton,PIN");
6585 return RETURN_OK;
6586}
6587
6588//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6589//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.
6590// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6591INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6592{
6593 if(!output)
6594 return RETURN_ERR;
6595 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6596
6597 return RETURN_OK;
6598}
6599
6600//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6601// 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
6602INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6603{
6604 //apply instantly. No setting need to be stored.
6605 char methods[MAX_BUF_SIZE], *token, *next_token;
6606 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6607 struct params params;
6608
6609 if(!methodString || !(apIndex==0 || apIndex==1))
6610 return RETURN_ERR;
6611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6612 //store the paramters, and wait for wifi up to apply
6613
6614 snprintf(methods, sizeof(methods), "%s", methodString);
6615 for(token=methods; *token; token=next_token)
6616 {
6617 strtok_r(token, ",", &next_token);
6618 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6619 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6620 else if(*token=='E')
6621 {
6622 if(!strcmp(methods, "Ethernet"))
6623 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6624 else if(!strcmp(methods, "ExternalNFCToken"))
6625 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6626 else
6627 printf("%s: Unknown WpsConfigMethod\n", __func__);
6628 }
6629 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6630 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6631 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6632 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6633 else if(*token=='P' )
6634 {
6635 if(!strcmp(token, "PushButton"))
6636 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6637 else if(!strcmp(token, "PIN"))
6638 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6639 else
6640 printf("%s: Unknown WpsConfigMethod\n", __func__);
6641 }
6642 else
6643 printf("%s: Unknown WpsConfigMethod\n", __func__);
6644 }
6645 params.name = "config_methods";
6646 params.value = config_methods;
6647 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6648 wifi_hostapdWrite(config_file, &params, 1);
6649 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6650 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6651
6652 return RETURN_OK;
6653}
6654
6655// outputs the pin value, ulong_pin must be allocated by the caller
6656INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6657{
6658 char buf[MAX_BUF_SIZE] = {0};
6659 char cmd[MAX_CMD_SIZE] = {0};
6660
6661 if(!output_ulong || !(apIndex==0 || apIndex==1))
6662 return RETURN_ERR;
6663 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6664 _syscmd(cmd, buf, sizeof(buf));
6665 if(strlen(buf) > 0)
6666 *output_ulong=strtoul(buf, NULL, 10);
6667
6668 return RETURN_OK;
6669}
6670
6671// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6672INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6673{
6674 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6675 char ap_pin[16] = {0};
6676 char buf[MAX_BUF_SIZE] = {0};
6677 char config_file[MAX_BUF_SIZE] = {0};
6678 ULONG prev_pin = 0;
6679 struct params params;
6680
6681 if(!(apIndex==0 || apIndex==1))
6682 return RETURN_ERR;
6683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6684 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6685 params.name = "ap_pin";
6686 params.value = ap_pin;
6687 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6688 wifi_hostapdWrite(config_file, &params, 1);
6689 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6690 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6691
6692 return RETURN_OK;
6693}
6694
6695// Output string is either Not configured or Configured, max 32 characters
6696INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6697{
6698 char cmd[MAX_CMD_SIZE];
6699 char buf[MAX_BUF_SIZE]={0};
6700
6701 if(!output_string || !(apIndex==0 || apIndex==1))
6702 return RETURN_ERR;
6703 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6704 snprintf(output_string, 32, "Not configured");
6705 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6706 _syscmd(cmd, buf, sizeof(buf));
6707
developer348e3d92022-09-13 14:48:41 +08006708 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006709 snprintf(output_string, 32, "Configured");
6710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6711
6712 return RETURN_OK;
6713}
6714
6715// sets the WPS pin for this AP
6716INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6717{
6718 char cmd[MAX_CMD_SIZE];
6719 char buf[MAX_BUF_SIZE]={0};
6720 BOOL enable;
6721
6722 if(!(apIndex==0 || apIndex==1))
6723 return RETURN_ERR;
6724 wifi_getApEnable(apIndex, &enable);
6725 if (!enable)
6726 return RETURN_ERR;
6727 wifi_getApWpsEnable(apIndex, &enable);
6728 if (!enable)
6729 return RETURN_ERR;
6730
6731 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6732 _syscmd(cmd, buf, sizeof(buf));
6733 if((strstr(buf, "OK"))!=NULL)
6734 return RETURN_OK;
6735
6736 return RETURN_ERR;
6737}
6738
6739// This function is called when the WPS push button has been pressed for this AP
6740INT wifi_setApWpsButtonPush(INT apIndex)
6741{
6742 char cmd[MAX_CMD_SIZE];
6743 char buf[MAX_BUF_SIZE]={0};
6744 BOOL enable=FALSE;
6745
6746 if(!(apIndex==0 || apIndex==1))
6747 return RETURN_ERR;
6748 wifi_getApEnable(apIndex, &enable);
6749 if (!enable)
6750 return RETURN_ERR;
6751
6752 wifi_getApWpsEnable(apIndex, &enable);
6753 if (!enable)
6754 return RETURN_ERR;
6755
6756 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6757 _syscmd(cmd, buf, sizeof(buf));
6758
6759 if((strstr(buf, "OK"))!=NULL)
6760 return RETURN_OK;
6761 return RETURN_ERR;
6762}
6763
6764// cancels WPS mode for this AP
6765INT wifi_cancelApWPS(INT apIndex)
6766{
6767 char cmd[MAX_CMD_SIZE];
6768 char buf[MAX_BUF_SIZE]={0};
6769
6770 if(!(apIndex==0 || apIndex==1))
6771 return RETURN_ERR;
6772 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6773 _syscmd(cmd,buf, sizeof(buf));
6774
6775 if((strstr(buf, "OK"))!=NULL)
6776 return RETURN_OK;
6777 return RETURN_ERR;
6778}
6779
6780//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6781//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6782INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6783{
6784 FILE *f;
6785 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6786 char cmd[256], buf[2048];
6787 char *param , *value, *line=NULL;
6788 size_t len = 0;
6789 ssize_t nread;
6790 wifi_associated_dev_t *dev=NULL;
6791
6792 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6793 *associated_dev_array = NULL;
6794 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6795 _syscmd(cmd,buf,sizeof(buf));
6796 *output_array_size = atoi(buf);
6797
6798 if (*output_array_size <= 0)
6799 return RETURN_OK;
6800
6801 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6802 *associated_dev_array = dev;
6803 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6804 _syscmd(cmd,buf,sizeof(buf));
6805 f = fopen("/tmp/connected_devices.txt", "r");
6806 if (f==NULL)
6807 {
6808 *output_array_size=0;
6809 return RETURN_ERR;
6810 }
6811 while ((nread = getline(&line, &len, f)) != -1)
6812 {
6813 param = strtok(line,"=");
6814 value = strtok(NULL,"=");
6815
6816 if( strcmp("flags",param) == 0 )
6817 {
6818 value[strlen(value)-1]='\0';
6819 if(strstr (value,"AUTHORIZED") != NULL )
6820 {
6821 dev[auth_temp].cli_AuthenticationState = 1;
6822 dev[auth_temp].cli_Active = 1;
6823 auth_temp++;
6824 read_flag=1;
6825 }
6826 }
6827 if(read_flag==1)
6828 {
6829 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6830 {
6831 value[strlen(value)-1]='\0';
6832 sscanf(value, "%x:%x:%x:%x:%x:%x",
6833 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6834 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6835 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6836 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6837 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6838 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6839 mac_temp++;
6840 read_flag=0;
6841 }
6842 }
6843 }
6844 *output_array_size = auth_temp;
6845 auth_temp=0;
6846 mac_temp=0;
6847 free(line);
6848 fclose(f);
6849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6850 return RETURN_OK;
6851}
6852
6853#define MACADDRESS_SIZE 6
6854
6855INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6856{
6857 FILE *fp = NULL;
6858 char str[MAX_BUF_SIZE] = {0};
6859 int wificlientindex = 0 ;
6860 int count = 0;
6861 int signalstrength = 0;
6862 int arr[MACADDRESS_SIZE] = {0};
6863 unsigned char mac[MACADDRESS_SIZE] = {0};
6864 UINT wifi_count = 0;
6865 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6866 char pipeCmd[MAX_CMD_SIZE] = {0};
6867
6868 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6869 *output_array_size = 0;
6870 *associated_dev_array = NULL;
6871
6872 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6873 fp = popen(pipeCmd, "r");
6874 if (fp == NULL)
6875 {
6876 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6877 return RETURN_ERR;
6878 }
6879
6880 /* Read the output a line at a time - output it. */
6881 fgets(str, sizeof(str)-1, fp);
6882 wifi_count = (unsigned int) atoi ( str );
6883 *output_array_size = wifi_count;
6884 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6885 pclose(fp);
6886
6887 if(wifi_count == 0)
6888 {
6889 return RETURN_OK;
6890 }
6891 else
6892 {
6893 wifi_associated_dev3_t* temp = NULL;
6894 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6895 if(temp == NULL)
6896 {
6897 printf("Error Statement. Insufficient memory \n");
6898 return RETURN_ERR;
6899 }
6900
6901 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6902 system(pipeCmd);
6903 memset(pipeCmd,0,sizeof(pipeCmd));
6904 if(apIndex == 0)
6905 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6906 else if(apIndex == 1)
6907 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6908 system(pipeCmd);
6909
6910 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6911 if(fp == NULL)
6912 {
6913 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6914 return RETURN_ERR;
6915 }
6916 fclose(fp);
6917
6918 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6919 fp = popen(pipeCmd, "r");
6920 if(fp)
6921 {
6922 for(count =0 ; count < wifi_count; count++)
6923 {
6924 fgets(str, MAX_BUF_SIZE, fp);
6925 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6926 {
6927 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6928 {
6929 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6930
6931 }
6932 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6933 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]);
6934 }
6935 temp[count].cli_AuthenticationState = 1; //TODO
6936 temp[count].cli_Active = 1; //TODO
6937 }
6938 pclose(fp);
6939 }
6940
6941 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6942 fp = popen(pipeCmd, "r");
6943 if(fp)
6944 {
6945 pclose(fp);
6946 }
6947 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6948 if(fp)
6949 {
6950 for(count =0 ; count < wifi_count ;count++)
6951 {
6952 fgets(str, MAX_BUF_SIZE, fp);
6953 signalstrength = atoi(str);
6954 temp[count].cli_SignalStrength = signalstrength;
6955 temp[count].cli_RSSI = signalstrength;
6956 temp[count].cli_SNR = signalstrength + 95;
6957 }
6958 pclose(fp);
6959 }
6960
6961
6962 if((apIndex == 0) || (apIndex == 4))
6963 {
6964 for(count =0 ; count < wifi_count ;count++)
6965 {
6966 strcpy(temp[count].cli_OperatingStandard,"g");
6967 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6968 }
6969
6970 //BytesSent
6971 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6972 fp = popen(pipeCmd, "r");
6973 if(fp)
6974 {
6975 pclose(fp);
6976 }
6977 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6978 if(fp)
6979 {
6980 for (count = 0; count < wifi_count; count++)
6981 {
6982 fgets(str, MAX_BUF_SIZE, fp);
6983 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6984 }
6985 pclose(fp);
6986 }
6987
6988 //BytesReceived
6989 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6990 fp = popen(pipeCmd, "r");
6991 if (fp)
6992 {
6993 pclose(fp);
6994 }
6995 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6996 if (fp)
6997 {
6998 for (count = 0; count < wifi_count; count++)
6999 {
7000 fgets(str, MAX_BUF_SIZE, fp);
7001 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7002 }
7003 pclose(fp);
7004 }
7005
7006 //PacketsSent
7007 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7008 fp = popen(pipeCmd, "r");
7009 if (fp)
7010 {
7011 pclose(fp);
7012 }
7013
7014 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7015 if (fp)
7016 {
7017 for (count = 0; count < wifi_count; count++)
7018 {
7019 fgets(str, MAX_BUF_SIZE, fp);
7020 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7021 }
7022 pclose(fp);
7023 }
7024
7025 //PacketsReceived
7026 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7027 fp = popen(pipeCmd, "r");
7028 if (fp)
7029 {
7030 pclose(fp);
7031 }
7032 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7033 if (fp)
7034 {
7035 for (count = 0; count < wifi_count; count++)
7036 {
7037 fgets(str, MAX_BUF_SIZE, fp);
7038 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7039 }
7040 pclose(fp);
7041 }
7042
7043 //ErrorsSent
7044 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7045 fp = popen(pipeCmd, "r");
7046 if (fp)
7047 {
7048 pclose(fp);
7049 }
7050 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7051 if (fp)
7052 {
7053 for (count = 0; count < wifi_count; count++)
7054 {
7055 fgets(str, MAX_BUF_SIZE, fp);
7056 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7057 }
7058 pclose(fp);
7059 }
7060
7061 //ErrorsSent
7062 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7063 fp = popen(pipeCmd, "r");
7064 if (fp)
7065 {
7066 pclose(fp);
7067 }
7068 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7069 if (fp)
7070 {
7071 for (count = 0; count < wifi_count; count++)
7072 {
7073 fgets(str, MAX_BUF_SIZE, fp);
7074 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7075 }
7076 pclose(fp);
7077 }
7078
7079 //LastDataDownlinkRate
7080 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7081 fp = popen(pipeCmd, "r");
7082 if (fp)
7083 {
7084 pclose(fp);
7085 }
7086 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7087 if (fp)
7088 {
7089 for (count = 0; count < wifi_count; count++)
7090 {
7091 fgets(str, MAX_BUF_SIZE, fp);
7092 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7093 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7094 }
7095 pclose(fp);
7096 }
7097
7098 //LastDataUplinkRate
7099 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7100 fp = popen(pipeCmd, "r");
7101 if (fp)
7102 {
7103 pclose(fp);
7104 }
7105 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7106 if (fp)
7107 {
7108 for (count = 0; count < wifi_count; count++)
7109 {
7110 fgets(str, MAX_BUF_SIZE, fp);
7111 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7112 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7113 }
7114 pclose(fp);
7115 }
7116
7117 }
7118 else if ((apIndex == 1) || (apIndex == 5))
7119 {
7120 for (count = 0; count < wifi_count; count++)
7121 {
7122 strcpy(temp[count].cli_OperatingStandard, "a");
7123 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7124 temp[count].cli_BytesSent = 0;
7125 temp[count].cli_BytesReceived = 0;
7126 temp[count].cli_LastDataUplinkRate = 0;
7127 temp[count].cli_LastDataDownlinkRate = 0;
7128 temp[count].cli_PacketsSent = 0;
7129 temp[count].cli_PacketsReceived = 0;
7130 temp[count].cli_ErrorsSent = 0;
7131 }
7132 }
7133
7134 for (count = 0; count < wifi_count; count++)
7135 {
7136 temp[count].cli_Retransmissions = 0;
7137 temp[count].cli_DataFramesSentAck = 0;
7138 temp[count].cli_DataFramesSentNoAck = 0;
7139 temp[count].cli_MinRSSI = 0;
7140 temp[count].cli_MaxRSSI = 0;
7141 strncpy(temp[count].cli_InterferenceSources, "", 64);
7142 memset(temp[count].cli_IPAddress, 0, 64);
7143 temp[count].cli_RetransCount = 0;
7144 temp[count].cli_FailedRetransCount = 0;
7145 temp[count].cli_RetryCount = 0;
7146 temp[count].cli_MultipleRetryCount = 0;
7147 }
7148 *associated_dev_array = temp;
7149 }
7150 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7151 return RETURN_OK;
7152}
7153
7154int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7155{
7156 FILE *fp = NULL;
7157 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7158 char cmd[MAX_CMD_SIZE];
7159 int count = 0;
7160
7161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7162 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7163 fp = popen(cmd,"r");
7164 if(fp == NULL)
7165 {
7166 printf("Failed to run command in Function %s\n",__FUNCTION__);
7167 return 0;
7168 }
7169 if(fgets(path, sizeof(path)-1, fp) != NULL)
7170 {
7171 for(count=0;path[count]!='\n';count++)
7172 status[count]=path[count];
7173 status[count]='\0';
7174 }
7175 strcpy(wifi_status,status);
7176 pclose(fp);
7177 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7178 return RETURN_OK;
7179}
7180
7181/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7182struct hostapd_sta_param {
7183 char key[50];
7184 char value[100];
7185}
7186
7187static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7188 int i = 0;
7189
7190 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7191 if (strncmp(params[i].key,key,50) == 0){
7192 return &params[i].value;
7193 }
7194 i++;
7195 }
7196 return NULL;
7197
7198} */
7199
7200static unsigned int count_occurences(const char *buf, const char *word)
7201{
7202 unsigned int n = 0;
7203 char *ptr = strstr(buf, word);
7204
7205 while (ptr++) {
7206 n++;
7207 ptr = strstr(ptr, word);
7208 }
7209
7210 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7211 return n;
7212}
7213
7214static const char *get_line_from_str_buf(const char *buf, char *line)
7215{
7216 int i;
7217 int n = strlen(buf);
7218
7219 for (i = 0; i < n; i++) {
7220 line[i] = buf[i];
7221 if (buf[i] == '\n') {
7222 line[i] = '\0';
7223 return &buf[i + 1];
7224 }
7225 }
7226
7227 return NULL;
7228}
7229
7230INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7231{
7232 unsigned int assoc_cnt = 0;
7233 char interface_name[50] = {0};
7234 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7235 char cmd[MAX_CMD_SIZE] = {'\0'};
7236 char line[256] = {'\0'};
7237 int i = 0;
7238 int ret = 0;
7239 const char *ptr = NULL;
7240 char *key = NULL;
7241 char *val = NULL;
7242 wifi_associated_dev3_t *temp = NULL;
7243 int rssi;
7244
7245 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7246
7247 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7248 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7249 return RETURN_ERR;
7250 }
7251
7252 // Example filtered output of 'iw dev' command:
7253 // Station 0a:69:72:10:d2:fa (on wifi0)
7254 // signal avg:-67 [-71, -71] dBm
7255 // Station 28:c2:1f:25:5f:99 (on wifi0)
7256 // signal avg:-67 [-71, -70] dBm
7257 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7258 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7259 return RETURN_ERR;
7260 }
7261
7262 ret = _syscmd(cmd, buf, sizeof(buf));
7263 if (ret == RETURN_ERR) {
7264 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7265 return RETURN_ERR;
7266 }
7267
7268 *output_array_size = count_occurences(buf, "Station");
7269 if (*output_array_size == 0) return RETURN_OK;
7270
7271 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7272 if (temp == NULL) {
7273 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7274 return RETURN_ERR;
7275 }
7276 *associated_dev_array = temp;
7277
7278 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7279 ptr = get_line_from_str_buf(buf, line);
7280 i = -1;
7281 while (ptr) {
7282 if (strstr(line, "Station")) {
7283 i++;
7284 key = strtok(line, " ");
7285 val = strtok(NULL, " ");
7286 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7287 &temp[i].cli_MACAddress[0],
7288 &temp[i].cli_MACAddress[1],
7289 &temp[i].cli_MACAddress[2],
7290 &temp[i].cli_MACAddress[3],
7291 &temp[i].cli_MACAddress[4],
7292 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7293 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7294 free(*associated_dev_array);
7295 return RETURN_ERR;
7296 }
7297 }
7298 else if (i < 0) {
7299 ptr = get_line_from_str_buf(ptr, line);
7300 continue; // We didn't detect 'station' entry yet
7301 }
7302 else if (strstr(line, "signal avg")) {
7303 key = strtok(line, ":");
7304 val = strtok(NULL, " ");
7305 if (sscanf(val, "%d", &rssi) <= 0 ) {
7306 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7307 free(*associated_dev_array);
7308 return RETURN_ERR;
7309 }
7310 temp[i].cli_RSSI = rssi;
7311 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7312 }
7313 // Here other fields can be parsed if added to filter of 'iw dev' command
7314
7315 ptr = get_line_from_str_buf(ptr, line);
7316 };
7317
7318 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7319
7320 return RETURN_OK;
7321}
7322
7323#if 0
7324//To-do
7325INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7326{
7327 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7328
7329 //Using different approach to get required WiFi Parameters from system available commands
7330#if 0
7331 FILE *f;
7332 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7333 char cmd[256], buf[2048];
7334 char *param , *value, *line=NULL;
7335 size_t len = 0;
7336 ssize_t nread;
7337 wifi_associated_dev3_t *dev=NULL;
7338 *associated_dev_array = NULL;
7339 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7340 _syscmd(cmd,buf,sizeof(buf));
7341 *output_array_size = atoi(buf);
7342
7343 if (*output_array_size <= 0)
7344 return RETURN_OK;
7345
7346 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7347 *associated_dev_array = dev;
7348 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7349 _syscmd(cmd,buf,sizeof(buf));
7350 f = fopen("/tmp/connected_devices.txt", "r");
7351 if (f==NULL)
7352 {
7353 *output_array_size=0;
7354 return RETURN_ERR;
7355 }
7356 while ((nread = getline(&line, &len, f)) != -1)
7357 {
7358 param = strtok(line,"=");
7359 value = strtok(NULL,"=");
7360
7361 if( strcmp("flags",param) == 0 )
7362 {
7363 value[strlen(value)-1]='\0';
7364 if(strstr (value,"AUTHORIZED") != NULL )
7365 {
7366 dev[auth_temp].cli_AuthenticationState = 1;
7367 dev[auth_temp].cli_Active = 1;
7368 auth_temp++;
7369 read_flag=1;
7370 }
7371 }
7372 if(read_flag==1)
7373 {
7374 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7375 {
7376 value[strlen(value)-1]='\0';
7377 sscanf(value, "%x:%x:%x:%x:%x:%x",
7378 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7379 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7380 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7381 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7382 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7383 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7384
7385 }
7386 else if( strcmp("rx_packets",param) == 0 )
7387 {
7388 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7389 }
7390
7391 else if( strcmp("tx_packets",param) == 0 )
7392 {
7393 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7394 }
7395
7396 else if( strcmp("rx_bytes",param) == 0 )
7397 {
7398 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7399 }
7400
7401 else if( strcmp("tx_bytes",param) == 0 )
7402 {
7403 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7404 mac_temp++;
7405 read_flag=0;
7406 }
7407 }
7408 }
7409
7410 *output_array_size = auth_temp;
7411 auth_temp=0;
7412 mac_temp=0;
7413 free(line);
7414 fclose(f);
7415#endif
7416 char interface_name[MAX_BUF_SIZE] = {0};
7417 char wifi_status[MAX_BUF_SIZE] = {0};
7418 char hostapdconf[MAX_BUF_SIZE] = {0};
7419
7420 wifi_associated_dev3_t *dev_array = NULL;
7421 ULONG wifi_count = 0;
7422
7423 *associated_dev_array = NULL;
7424 *output_array_size = 0;
7425
7426 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7427 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7428 {
7429 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7430
7431 GetInterfaceName(interface_name, hostapdconf);
7432
7433 if(strlen(interface_name) > 1)
7434 {
7435 wifihal_interfacestatus(wifi_status,interface_name);
7436 if(strcmp(wifi_status,"RUNNING") == 0)
7437 {
7438 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7439
7440 *associated_dev_array = dev_array;
7441 *output_array_size = wifi_count;
7442 }
7443 else
7444 {
7445 *associated_dev_array = NULL;
7446 }
7447 }
7448 }
7449
7450 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7451 return RETURN_OK;
7452}
7453#endif
7454
7455/* getIPAddress function */
7456/**
7457* @description Returning IpAddress of the Matched String
7458*
7459* @param
7460* @str Having MacAddress
7461* @ipaddr Having ipaddr
7462* @return The status of the operation
7463* @retval RETURN_OK if successful
7464* @retval RETURN_ERR if any error is detected
7465*
7466*/
7467
7468INT getIPAddress(char *str,char *ipaddr)
7469{
7470 FILE *fp = NULL;
7471 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7472 int LeaseTime = 0,ret = 0;
7473 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7474 {
7475 return RETURN_ERR;
7476 }
7477
7478 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7479 {
7480 /*
7481 Sample:sss
7482 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7483 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7484 */
7485 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7486 &(LeaseTime),
7487 phyAddr,
7488 ipAddr,
7489 hostName
7490 );
7491 if(ret != 4)
7492 continue;
7493 if(strcmp(str,phyAddr) == 0)
7494 strcpy(ipaddr,ipAddr);
7495 }
7496 return RETURN_OK;
7497}
7498
7499/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7500/**
7501* @description Returning Inactive wireless connected clients informations
7502*
7503* @param
7504* @filename Holding private_wifi 2g/5g content files
7505* @associated_dev_array Having inactiv wireless clients informations
7506* @output_array_size Returning Inactive wireless counts
7507* @return The status of the operation
7508* @retval RETURN_OK if successful
7509* @retval RETURN_ERR if any error is detected
7510*
7511*/
7512
7513INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7514{
7515 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7516 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7517 FILE *fp = NULL;
7518 int arr[MACADDRESS_SIZE] = {0};
7519 unsigned char mac[MACADDRESS_SIZE] = {0};
7520 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7521 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7522 fp = popen(buf,"r");
7523 if(fp == NULL)
7524 return RETURN_ERR;
7525 else
7526 {
7527 fgets(path,sizeof(path),fp);
7528 maccount = atoi(path);
7529 }
7530 pclose(fp);
7531 *output_array_size = maccount;
7532 wifi_associated_dev3_t* temp = NULL;
7533 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7534 *associated_dev_array = temp;
7535 if(temp == NULL)
7536 {
7537 printf("Error Statement. Insufficient memory \n");
7538 return RETURN_ERR;
7539 }
7540 memset(buf,0,sizeof(buf));
7541 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7542 fp = popen(buf,"r");
7543 for(count = 0; count < maccount ; count++)
7544 {
7545 fgets(path,sizeof(path),fp);
7546 for(i = 0; path[i]!='\n';i++)
7547 str[i]=path[i];
7548 str[i]='\0';
7549 getIPAddress(str,ipaddr);
7550 memset(buf,0,sizeof(buf));
7551 if(strlen(ipaddr) > 0)
7552 {
7553 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7554 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7555 {
7556 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7557 {
7558 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7559 {
7560 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7561
7562 }
7563 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7564 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]);
7565 }
7566 temp[count].cli_AuthenticationState = 0; //TODO
7567 temp[count].cli_Active = 0; //TODO
7568 temp[count].cli_SignalStrength = 0;
7569 }
7570 else //Active wireless clients info
7571 {
7572 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7573 {
7574 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7575 {
7576 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7577
7578 }
7579 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7580 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]);
7581 }
7582 temp[count].cli_Active = 1;
7583 }
7584 }
7585 memset(ipaddr,0,sizeof(ipaddr));
7586 }
7587 pclose(fp);
7588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7589 return RETURN_OK;
7590}
7591//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7592//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7593//To get Band Steering Capability
7594INT wifi_getBandSteeringCapability(BOOL *support)
7595{
7596 *support = FALSE;
7597 return RETURN_OK;
7598}
7599
7600
7601//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7602//To get Band Steering enable status
7603INT wifi_getBandSteeringEnable(BOOL *enable)
7604{
7605 *enable = FALSE;
7606 return RETURN_OK;
7607}
7608
7609//To turn on/off Band steering
7610INT wifi_setBandSteeringEnable(BOOL enable)
7611{
7612 return RETURN_OK;
7613}
7614
7615//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7616//To get Band Steering AP group
7617INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7618{
7619 if (NULL == output_ApGroup)
7620 return RETURN_ERR;
7621
7622 strcpy(output_ApGroup, "1,2");
7623 return RETURN_OK;
7624}
7625
7626//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7627//to set and read the band steering BandUtilizationThreshold parameters
7628INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7629{
7630 return RETURN_ERR;
7631}
7632
7633INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7634{
7635 return RETURN_ERR;
7636}
7637
7638//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7639//to set and read the band steering RSSIThreshold parameters
7640INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7641{
7642 return RETURN_ERR;
7643}
7644
7645INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7646{
7647 return RETURN_ERR;
7648}
7649
7650
7651//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7652//to set and read the band steering physical modulation rate threshold parameters
7653INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7654{
7655 //If chip is not support, return -1
7656 return RETURN_ERR;
7657}
7658
7659INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7660{
7661 //If chip is not support, return -1
7662 return RETURN_ERR;
7663}
7664
7665//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7666//to set and read the inactivity time (in seconds) for steering under overload condition
7667INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7668{
7669 return RETURN_ERR;
7670}
7671
7672INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7673{
7674 return RETURN_ERR;
7675}
7676
7677//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7678//to set and read the inactivity time (in seconds) for steering under Idle condition
7679INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7680{
7681 return RETURN_ERR;
7682}
7683
7684INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7685{
7686 return RETURN_ERR;
7687}
7688
7689//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7690//pClientMAC[64]
7691//pSourceSSIDIndex[64]
7692//pDestSSIDIndex[64]
7693//pSteeringReason[256]
7694INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7695{
7696 //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
7697 *pSteeringTime=time(NULL);
7698 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7699 return RETURN_OK;
7700}
7701
7702INT wifi_ifConfigDown(INT apIndex)
7703{
7704 INT status = RETURN_OK;
7705 char cmd[64];
7706
7707 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7708 printf("%s: %s\n", __func__, cmd);
7709 system(cmd);
7710
7711 return status;
7712}
7713
7714INT wifi_ifConfigUp(INT apIndex)
7715{
7716 char cmd[128];
7717 char buf[1024];
7718
7719 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7720 _syscmd(cmd, buf, sizeof(buf));
7721 return 0;
7722}
7723
7724//>> Deprecated. Replace with wifi_applyRadioSettings
7725INT wifi_pushBridgeInfo(INT apIndex)
7726{
7727 char ip[32];
7728 char subnet[32];
7729 char bridge[32];
7730 int vlanId;
7731 char cmd[128];
7732 char buf[1024];
7733
7734 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7735 wifi_getApVlanID(apIndex,&vlanId);
7736
7737 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7738 _syscmd(cmd,buf, sizeof(buf));
7739
7740 return 0;
7741}
7742
7743INT wifi_pushChannel(INT radioIndex, UINT channel)
7744{
7745 char cmd[128];
7746 char buf[1024];
7747 int apIndex;
7748
7749 apIndex=(radioIndex==0)?0:1;
7750 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7751 _syscmd(cmd,buf, sizeof(buf));
7752
7753 return 0;
7754}
7755
7756INT wifi_pushChannelMode(INT radioIndex)
7757{
7758 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7759 return RETURN_ERR;
7760}
7761
7762INT wifi_pushDefaultValues(INT radioIndex)
7763{
7764 //Apply Comcast specified default radio settings instantly
7765 //AMPDU=1
7766 //AMPDUFrames=32
7767 //AMPDULim=50000
7768 //txqueuelen=1000
7769
7770 return RETURN_ERR;
7771}
7772
7773INT wifi_pushTxChainMask(INT radioIndex)
7774{
7775 //Apply default TxChainMask instantly
7776 return RETURN_ERR;
7777}
7778
7779INT wifi_pushRxChainMask(INT radioIndex)
7780{
7781 //Apply default RxChainMask instantly
7782 return RETURN_ERR;
7783}
7784
7785INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7786{
7787 INT status;
7788
7789 status = wifi_setSSIDName(apIndex,ssid);
7790 wifi_setApEnable(apIndex,FALSE);
7791 wifi_setApEnable(apIndex,TRUE);
7792
7793 return status;
7794}
7795
7796INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7797{
7798 //Apply default Ssid Advertisement instantly
7799 return RETURN_ERR;
7800}
7801
7802INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7803{
7804 INT status = RETURN_ERR;
7805 *output = 0;
7806 return RETURN_ERR;
7807}
7808
7809INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7810{
7811 return RETURN_OK;
7812}
7813
7814INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7815{
7816 return RETURN_OK;
7817}
7818
7819//To-do
7820INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7821{
developereb199ae2022-09-13 14:04:27 +08007822 char output[16]={'\0'};
7823 char config_file[MAX_BUF_SIZE] = {0};
7824
7825 if (!output_string)
7826 return RETURN_ERR;
7827
7828 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7829 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7830
7831 if (strlen(output) == 0)
7832 snprintf(output_string, 64, "Disabled");
7833 else if (strncmp(output, "0", 1) == 0)
7834 snprintf(output_string, 64, "Disabled");
7835 else if (strncmp(output, "1", 1) == 0)
7836 snprintf(output_string, 64, "Optional");
7837 else if (strncmp(output, "2", 1) == 0)
7838 snprintf(output_string, 64, "Required");
7839 else {
7840 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7841 return RETURN_ERR;
7842 }
7843
7844 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007845 return RETURN_OK;
7846}
7847INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7848{
developereb199ae2022-09-13 14:04:27 +08007849 char str[MAX_BUF_SIZE]={'\0'};
7850 char cmd[MAX_CMD_SIZE]={'\0'};
7851 struct params params;
7852 char config_file[MAX_BUF_SIZE] = {0};
7853
7854 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7855 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7856 return RETURN_ERR;
7857
7858 params.name = "ieee80211w";
7859 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7860 params.value = "0";
7861 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7862 params.value = "1";
7863 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7864 params.value = "2";
7865 else{
7866 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7867 return RETURN_ERR;
7868 }
7869 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7870 wifi_hostapdWrite(config_file, &params, 1);
7871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007872 return RETURN_OK;
7873}
7874INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7875{
7876 char output[16]={'\0'};
7877 char config_file[MAX_BUF_SIZE] = {0};
7878
7879 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7880 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7881 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7882
7883 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7884 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7885
7886 return RETURN_OK;
7887}
7888
7889INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7890{
7891 return RETURN_OK;
7892}
7893
7894INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7895{
7896 return RETURN_OK;
7897}
7898
7899INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7900{
7901 return RETURN_OK;
7902}
7903
7904INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7905{
7906 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7907 char config_file[MAX_BUF_SIZE] = {0};
7908
7909 if (NULL == output)
7910 return RETURN_ERR;
7911 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7912 wifi_hostapdRead(config_file,"hw_mode",output,64);
7913
7914 if(strcmp(output,"b")==0)
7915 sprintf(output, "%s", "1,2,5.5,11");
7916 else if (strcmp(output,"a")==0)
7917 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7918 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7919 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7920
7921 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7922 return RETURN_OK;
7923}
7924
7925INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7926{
7927 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7928 char *temp;
7929 char temp_output[128];
7930 char temp_TransmitRates[128];
7931 char config_file[MAX_BUF_SIZE] = {0};
7932
7933 if (NULL == output)
7934 return RETURN_ERR;
7935
7936 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7937 wifi_hostapdRead(config_file,"supported_rates",output,64);
7938
7939 strcpy(temp_TransmitRates,output);
7940 strcpy(temp_output,"");
7941 temp = strtok(temp_TransmitRates," ");
7942 while(temp!=NULL)
7943 {
7944 temp[strlen(temp)-1]=0;
7945 if((temp[0]=='5') && (temp[1]=='\0'))
7946 {
7947 temp="5.5";
7948 }
7949 strcat(temp_output,temp);
7950 temp = strtok(NULL," ");
7951 if(temp!=NULL)
7952 {
7953 strcat(temp_output,",");
7954 }
7955 }
7956 strcpy(output,temp_output);
7957 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7958
7959 return RETURN_OK;
7960}
7961
7962INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7963{
7964 return RETURN_OK;
7965}
7966
7967
7968INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7969{
7970 int i=0;
7971 char *temp;
7972 char temp1[128];
7973 char temp_output[128];
7974 char temp_TransmitRates[128];
7975 struct params params={'\0'};
7976 char config_file[MAX_BUF_SIZE] = {0};
7977
7978 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7979 if(NULL == output)
7980 return RETURN_ERR;
7981
7982 strcpy(temp_TransmitRates,output);
7983
7984 for(i=0;i<strlen(temp_TransmitRates);i++)
7985 {
7986 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7987 {
7988 continue;
7989 }
7990 else
7991 {
7992 return RETURN_ERR;
7993 }
7994 }
7995 strcpy(temp_output,"");
7996 temp = strtok(temp_TransmitRates," ");
7997 while(temp!=NULL)
7998 {
7999 strcpy(temp1,temp);
8000 if(wlanIndex==1)
8001 {
8002 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8003 {
8004 return RETURN_ERR;
8005 }
8006 }
8007
8008 if(strcmp(temp,"5.5")==0)
8009 {
8010 strcpy(temp1,"55");
8011 }
8012 else
8013 {
8014 strcat(temp1,"0");
8015 }
8016 strcat(temp_output,temp1);
8017 temp = strtok(NULL," ");
8018 if(temp!=NULL)
8019 {
8020 strcat(temp_output," ");
8021 }
8022 }
8023 strcpy(output,temp_output);
8024
8025
8026 params.name = "supported_rates";
8027 params.value = output;
8028
8029 wifi_dbg_printf("\n%s:",__func__);
8030 wifi_dbg_printf("params.value=%s\n",params.value);
8031 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8032 wifi_hostapdWrite(config_file,&params,1);
8033 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8034
8035 return RETURN_OK;
8036}
8037
8038
8039static char *sncopy(char *dst, int dst_sz, const char *src)
8040{
8041 if (src && dst && dst_sz > 0) {
8042 strncpy(dst, src, dst_sz);
8043 dst[dst_sz - 1] = '\0';
8044 }
8045 return dst;
8046}
8047
8048static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8049{
8050 if (0 == strcmp(ht_mode, "HT40") ||
8051 0 == strcmp(ht_mode, "HT80") ||
8052 0 == strcmp(ht_mode, "HT160")) {
8053 switch (channel) {
8054 case 1 ... 7:
8055 case 36:
8056 case 44:
8057 case 52:
8058 case 60:
8059 case 100:
8060 case 108:
8061 case 116:
8062 case 124:
8063 case 132:
8064 case 140:
8065 case 149:
8066 case 157:
8067 return 1;
8068 case 8 ... 13:
8069 case 40:
8070 case 48:
8071 case 56:
8072 case 64:
8073 case 104:
8074 case 112:
8075 case 120:
8076 case 128:
8077 case 136:
8078 case 144:
8079 case 153:
8080 case 161:
8081 return -1;
8082 default:
8083 return -EINVAL;
8084 }
8085 }
8086
8087 return -EINVAL;
8088}
8089
8090static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8091{
8092 if (NULL == hw_mode) return;
8093
8094 if (0 == strcmp(hw_mode, "ac"))
8095 sncopy(bw_mode, bw_mode_len, "ht vht");
8096
8097 if (0 == strcmp(hw_mode, "n"))
8098 sncopy(bw_mode, bw_mode_len, "ht");
8099
8100 return;
8101}
8102
8103static int util_chan_to_freq(int chan)
8104{
8105 if (chan == 14)
8106 return 2484;
8107 else if (chan < 14)
8108 return 2407 + chan * 5;
8109 else if (chan >= 182 && chan <= 196)
8110 return 4000 + chan * 5;
8111 else
8112 return 5000 + chan * 5;
8113 return 0;
8114}
8115
8116const int *util_unii_5g_chan2list(int chan, int width)
8117{
8118 static const int lists[] = {
8119 // <width>, <chan1>, <chan2>..., 0,
8120 20, 36, 0,
8121 20, 40, 0,
8122 20, 44, 0,
8123 20, 48, 0,
8124 20, 52, 0,
8125 20, 56, 0,
8126 20, 60, 0,
8127 20, 64, 0,
8128 20, 100, 0,
8129 20, 104, 0,
8130 20, 108, 0,
8131 20, 112, 0,
8132 20, 116, 0,
8133 20, 120, 0,
8134 20, 124, 0,
8135 20, 128, 0,
8136 20, 132, 0,
8137 20, 136, 0,
8138 20, 140, 0,
8139 20, 144, 0,
8140 20, 149, 0,
8141 20, 153, 0,
8142 20, 157, 0,
8143 20, 161, 0,
8144 20, 165, 0,
8145 40, 36, 40, 0,
8146 40, 44, 48, 0,
8147 40, 52, 56, 0,
8148 40, 60, 64, 0,
8149 40, 100, 104, 0,
8150 40, 108, 112, 0,
8151 40, 116, 120, 0,
8152 40, 124, 128, 0,
8153 40, 132, 136, 0,
8154 40, 140, 144, 0,
8155 40, 149, 153, 0,
8156 40, 157, 161, 0,
8157 80, 36, 40, 44, 48, 0,
8158 80, 52, 56, 60, 64, 0,
8159 80, 100, 104, 108, 112, 0,
8160 80, 116, 120, 124, 128, 0,
8161 80, 132, 136, 140, 144, 0,
8162 80, 149, 153, 157, 161, 0,
8163 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8164 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8165 -1 // final delimiter
8166 };
8167 const int *start;
8168 const int *p;
8169
8170 for (p = lists; *p != -1; p++) {
8171 if (*p == width) {
8172 for (start = ++p; *p != 0; p++) {
8173 if (*p == chan)
8174 return start;
8175 }
8176 }
8177 // move to the end of channel list of given width
8178 while (*p != 0) {
8179 p++;
8180 }
8181 }
8182
8183 return NULL;
8184}
8185
8186static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8187{
8188 if (NULL == ht_mode)
8189 return 0;
8190
8191 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8192 const int *chans = util_unii_5g_chan2list(channel, width);
8193 int sum = 0;
8194 int cnt = 0;
8195
8196 if (NULL == chans)
8197 return 0;
8198
8199 while (*chans) {
8200 sum += *chans;
8201 cnt++;
8202 chans++;
8203 }
8204 return sum / cnt;
8205}
8206
8207static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8208{
8209 BOOL onlyG, onlyN, onlyA;
8210 CHAR tmp[64];
8211 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8212 if (ret == RETURN_OK) {
8213 sncopy(hw_mode, hw_mode_size, tmp);
8214 }
8215 return ret;
8216}
8217
8218INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8219{
8220 // Sample commands:
8221 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8222 // hostapd_cli -i wifi0 chan_switch 30 2437
8223 char cmd[MAX_CMD_SIZE] = {0};
8224 char buf[MAX_BUF_SIZE] = {0};
8225 int freq = 0, ret = 0;
8226 char center_freq1_str[32] = ""; // center_freq1=%d
8227 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8228 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8229 char hw_mode[16] = ""; // n|ac
8230 char bw_mode[16] = ""; // ht|ht vht
8231 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8232 int sec_chan_offset;
8233 int width;
developer4fb0b922022-09-30 14:29:09 +08008234 char config_file[64] = {0};
8235 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008236 char *ext_str = "None";
8237
developer4fb0b922022-09-30 14:29:09 +08008238 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008239
8240 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8241
developer5884e982022-10-06 10:52:50 +08008242 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008243
8244 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008245 if (channel){
8246 freq = util_chan_to_freq(channel);
8247 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8248 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8249 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8250 if (sec_chan_offset != -EINVAL)
8251 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008252
8253
developer5884e982022-10-06 10:52:50 +08008254 // Provide bandwith if specified
8255 if (channel_width_MHz > 20) {
8256 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8257 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8258 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008259
developer5884e982022-10-06 10:52:50 +08008260 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8261 }else if (channel_width_MHz == 20){
8262 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8263 }
developer06a01d92022-09-07 16:32:39 +08008264
developer5884e982022-10-06 10:52:50 +08008265 int center_chan = 0;
8266 if (channel_width_MHz > 20) {
8267 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8268 if (center_chan > 0) {
8269 int center_freq1 = util_chan_to_freq(center_chan);
8270 if (center_freq1)
8271 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8272 }
developer06a01d92022-09-07 16:32:39 +08008273 }
developer06a01d92022-09-07 16:32:39 +08008274
developer5884e982022-10-06 10:52:50 +08008275 // Only the first AP, other are hanging on the same radio
8276 int apIndex = radioIndex;
8277 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8278 AP_PREFIX, apIndex, csa_beacon_count, freq,
8279 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8280 wifi_dbg_printf("execute: '%s'\n", cmd);
8281 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008282
developer5884e982022-10-06 10:52:50 +08008283 ret = wifi_setRadioChannel(radioIndex, channel);
8284 if (ret != RETURN_OK) {
8285 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8286 return RETURN_ERR;
8287 }
8288
8289 if (sec_chan_offset == 1) ext_str = "Above";
8290 else if (sec_chan_offset == -1) ext_str = "Below";
8291
8292 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008293
developer5884e982022-10-06 10:52:50 +08008294 } else {
8295 if (channel_width_MHz > 20)
8296 ext_str = "Above";
8297 }
developer4fb0b922022-09-30 14:29:09 +08008298 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8299 _syscmd(cmd, buf, sizeof(buf));
8300 if (strlen(buf) != 0)
8301 stbcEnable = TRUE;
8302
developer06a01d92022-09-07 16:32:39 +08008303 wifi_setRadioExtChannel(radioIndex, ext_str);
8304
developer4fb0b922022-09-30 14:29:09 +08008305 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8306
developer06a01d92022-09-07 16:32:39 +08008307 char mhz_str[16];
8308 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8309 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8310
8311 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8312
8313 return RETURN_OK;
8314}
8315
8316INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8317{
developer615510b2022-09-27 10:14:35 +08008318 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008319 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008320 char cmd[256]={0};
8321 char buf[128]={0};
8322 char file_name[32] = {0};
8323 char filter_SSID[32] = {0};
8324 char line[256] = {0};
8325 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008326 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008327 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008328 size_t len=0;
8329 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008330 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008331 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008332 bool filter_enable = false;
8333 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008334
developer615510b2022-09-27 10:14:35 +08008335 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008336
developer615510b2022-09-27 10:14:35 +08008337 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8338 f = fopen(file_name, "r");
8339 if (f != NULL) {
8340 fgets(filter_SSID, sizeof(file_name), f);
8341 if (strlen(filter_SSID) != 0)
8342 filter_enable = true;
8343 fclose(f);
8344 }
8345
8346 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8347 _syscmd(cmd, buf, sizeof(buf));
8348 channels_num = strtol(buf, NULL, 10);
8349
developer615510b2022-09-27 10:14:35 +08008350 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8351 // 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);
8352 fprintf(stderr, "cmd: %s\n", cmd);
8353 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008354 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8355 return RETURN_ERR;
8356 }
developer5550e242022-09-30 09:59:32 +08008357
8358 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8359 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8360
developer615510b2022-09-27 10:14:35 +08008361 ret = fgets(line, sizeof(line), f);
8362 while (ret != NULL) {
8363 if(strstr(line, "BSS") != NULL) { // new neighbor info
8364 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8365 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8366 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8367
8368 if (!filter_BSS) {
8369 index++;
8370 wifi_neighbor_ap2_t *tmp;
8371 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8372 if (tmp == NULL) { // no more memory to use
8373 index--;
8374 wifi_dbg_printf("%s: realloc failed\n", __func__);
8375 break;
8376 }
8377 scan_array = tmp;
8378 }
8379 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008380
developer615510b2022-09-27 10:14:35 +08008381 filter_BSS = false;
8382 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8383 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8384 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8385 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8386 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008387 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008388 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008389
developer615510b2022-09-27 10:14:35 +08008390 if (freq >= 2412 && freq <= 2484) {
8391 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8392 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8393 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8394 }
8395 else if (freq >= 5160 && freq <= 5805) {
8396 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8397 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8398 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8399 }
developer06a01d92022-09-07 16:32:39 +08008400
developer615510b2022-09-27 10:14:35 +08008401 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008402 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008403 for (int i = 0; i < channels_num; i++) {
8404 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8405 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8406 break;
8407 }
8408 }
developer06a01d92022-09-07 16:32:39 +08008409 }
developer615510b2022-09-27 10:14:35 +08008410 } else if (strstr(line, "beacon interval") != NULL) {
8411 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8412 } else if (strstr(line, "signal") != NULL) {
8413 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8414 } else if (strstr(line,"SSID") != NULL) {
8415 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8416 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8417 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008418 }
developer615510b2022-09-27 10:14:35 +08008419 } else if (strstr(line, "Supported rates") != NULL) {
8420 char SRate[80] = {0}, *tmp = NULL;
8421 memset(buf, 0, sizeof(buf));
8422 strcpy(SRate, line);
8423 tmp = strtok(SRate, ":");
8424 tmp = strtok(NULL, ":");
8425 strcpy(buf, tmp);
8426 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008427
developer615510b2022-09-27 10:14:35 +08008428 tmp = strtok(buf, " \n");
8429 while (tmp != NULL) {
8430 strcat(SRate, tmp);
8431 if (SRate[strlen(SRate) - 1] == '*') {
8432 SRate[strlen(SRate) - 1] = '\0';
8433 }
8434 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008435
developer615510b2022-09-27 10:14:35 +08008436 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008437 }
developer615510b2022-09-27 10:14:35 +08008438 SRate[strlen(SRate) - 1] = '\0';
8439 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8440 } else if (strstr(line, "DTIM") != NULL) {
8441 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8442 } else if (strstr(line, "VHT capabilities") != NULL) {
8443 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8444 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8445 } else if (strstr(line, "HT capabilities") != NULL) {
8446 strcat(scan_array[index].ap_SupportedStandards, ",n");
8447 strcpy(scan_array[index].ap_OperatingStandards, "n");
8448 } else if (strstr(line, "VHT operation") != NULL) {
8449 ret = fgets(line, sizeof(line), f);
8450 sscanf(line," * channel width: %d", &vht_channel_width);
8451 if(vht_channel_width == 1) {
8452 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8453 } else {
8454 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8455 }
8456 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8457 continue;
8458 } else if (strstr(line, "HT operation") != NULL) {
8459 ret = fgets(line, sizeof(line), f);
8460 sscanf(line," * secondary channel offset: %s", &buf);
8461 if (!strcmp(buf, "above")) {
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_HT40PLUS", radio_index%1 ? "A": "G");
developer06a01d92022-09-07 16:32:39 +08008464 }
developer615510b2022-09-27 10:14:35 +08008465 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008466 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008467 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8468 } else {
8469 //20Mhz
8470 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 +08008471 }
developer615510b2022-09-27 10:14:35 +08008472 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008473 continue;
developer615510b2022-09-27 10:14:35 +08008474 } else if (strstr(line, "HE capabilities") != NULL) {
8475 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8476 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8477 ret = fgets(line, sizeof(line), f);
8478 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8479 if (strstr(line, "HE40/2.4GHz") != NULL)
8480 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8481 else
8482 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8483 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8484 if (strstr(line, "HE80/5GHz") != NULL) {
8485 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8486 ret = fgets(line, sizeof(line), f);
8487 } else
8488 continue;
8489 if (strstr(line, "HE160/5GHz") != NULL)
8490 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008491 }
developer615510b2022-09-27 10:14:35 +08008492 continue;
8493 } else if (strstr(line, "WPA") != NULL) {
8494 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8495 } else if (strstr(line, "RSN") != NULL) {
8496 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8497 } else if (strstr(line, "Group cipher") != NULL) {
8498 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8499 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8500 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008501 }
developer06a01d92022-09-07 16:32:39 +08008502 }
developer615510b2022-09-27 10:14:35 +08008503 ret = fgets(line, sizeof(line), f);
8504 }
8505
8506 if (!filter_BSS) {
8507 *output_array_size = index + 1;
8508 } else {
8509 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8510 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008511 }
developer06a01d92022-09-07 16:32:39 +08008512 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008513 pclose(f);
developer5550e242022-09-30 09:59:32 +08008514 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008516 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008517}
developer615510b2022-09-27 10:14:35 +08008518
developer06a01d92022-09-07 16:32:39 +08008519INT wifi_getApAssociatedDeviceStats(
8520 INT apIndex,
8521 mac_address_t *clientMacAddress,
8522 wifi_associated_dev_stats_t *associated_dev_stats,
8523 u64 *handle)
8524{
8525 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8526 char interface_name[50] = {0};
8527 char cmd[1024] = {0};
8528 char mac_str[18] = {0};
8529 char *key = NULL;
8530 char *val = NULL;
8531 FILE *f = NULL;
8532 char *line = NULL;
8533 size_t len = 0;
8534 ssize_t read = 0;
8535
8536 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8537 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8538 return RETURN_ERR;
8539 }
8540
8541 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8542 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8543 if((f = popen(cmd, "r")) == NULL) {
8544 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8545 return RETURN_ERR;
8546 }
8547
8548 while ((read = getline(&line, &len, f)) != -1) {
8549 key = strtok(line,":");
8550 val = strtok(NULL,":");
8551
8552 if(!strncmp(key,"rx bytes",8))
8553 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8554 if(!strncmp(key,"tx bytes",8))
8555 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8556 if(!strncmp(key,"rx packets",10))
8557 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8558 if(!strncmp(key,"tx packets",10))
8559 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8560 if(!strncmp(key,"tx retries",10))
8561 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8562 if(!strncmp(key,"tx failed",9))
8563 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8564 if(!strncmp(key,"rx drop misc",13))
8565 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8566 if(!strncmp(key,"rx bitrate",10)) {
8567 val = strtok(val, " ");
8568 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8569 }
8570 if(!strncmp(key,"tx bitrate",10)) {
8571 val = strtok(val, " ");
8572 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8573 }
8574 }
8575 free(line);
8576 pclose(f);
8577 return RETURN_OK;
8578}
8579
8580INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8581{
8582 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8583
8584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8585 if (NULL == output_string)
8586 return RETURN_ERR;
8587
8588 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8589 _syscmd(cmd, buf, sizeof(buf));
8590
8591 //size of SSID name restricted to value less than 32 bytes
8592 snprintf(output_string, 32, "%s", buf);
8593 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8594
8595 return RETURN_OK;
8596}
8597
8598INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8599{
8600 //char cmd[MAX_CMD_SIZE] = {0};
8601 char config_file[MAX_BUF_SIZE] = {0};
8602 char buf[32] = {0};
8603
8604 if (!output_filterMode)
8605 return RETURN_ERR;
8606
8607 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8608 //_syscmd(cmd, buf, sizeof(buf));
8609 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8610 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008611 if(strlen(buf) == 0) {
8612 *output_filterMode = 0;
8613 }
8614 else {
8615 int macaddr_acl_mode = strtol(buf, NULL, 10);
8616 if (macaddr_acl_mode == 1) {
8617 *output_filterMode = 1;
8618 } else if (macaddr_acl_mode == 0) {
8619 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8620 if (strlen(buf) == 0) {
8621 *output_filterMode = 0;
8622 } else {
8623 *output_filterMode = 2;
8624 }
8625 } else {
8626 return RETURN_ERR;
8627 }
8628 }
developer06a01d92022-09-07 16:32:39 +08008629
8630 return RETURN_OK;
8631}
8632
8633INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8634{
8635 FILE *fp = NULL;
8636 char str[MAX_BUF_SIZE] = {0};
8637 int wificlientindex = 0 ;
8638 int count = 0;
8639 int signalstrength = 0;
8640 int arr[MACADDRESS_SIZE] = {0};
8641 unsigned char mac[MACADDRESS_SIZE] = {0};
8642 UINT wifi_count = 0;
8643 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8644 char pipeCmd[MAX_CMD_SIZE] = {0};
8645
8646 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8647 *output_array_size = 0;
8648 *associated_dev_array = NULL;
8649 char interface_name[50] = {0};
8650
8651 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8652 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8653 return RETURN_ERR;
8654 }
8655
8656 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8657 fp = popen(pipeCmd, "r");
8658 if (fp == NULL)
8659 {
8660 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8661 return RETURN_ERR;
8662 }
8663
8664 /* Read the output a line at a time - output it. */
8665 fgets(str, sizeof(str)-1, fp);
8666 wifi_count = (unsigned int) atoi ( str );
8667 *output_array_size = wifi_count;
8668 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8669 pclose(fp);
8670
8671 if(wifi_count == 0)
8672 {
8673 return RETURN_OK;
8674 }
8675 else
8676 {
8677 wifi_associated_dev2_t* temp = NULL;
8678 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8679 *associated_dev_array = temp;
8680 if(temp == NULL)
8681 {
8682 printf("Error Statement. Insufficient memory \n");
8683 return RETURN_ERR;
8684 }
8685
8686 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8687 system(pipeCmd);
8688
8689 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8690 if(fp == NULL)
8691 {
8692 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8693 return RETURN_ERR;
8694 }
8695 fclose(fp);
8696
8697 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8698 fp = popen(pipeCmd, "r");
8699 if(fp)
8700 {
8701 for(count =0 ; count < wifi_count; count++)
8702 {
8703 fgets(str, MAX_BUF_SIZE, fp);
8704 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8705 {
8706 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8707 {
8708 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8709
8710 }
8711 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8712 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]);
8713 }
8714 temp[count].cli_AuthenticationState = 1; //TODO
8715 temp[count].cli_Active = 1; //TODO
8716 }
8717 pclose(fp);
8718 }
8719
8720 //Updating RSSI per client
8721 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8722 fp = popen(pipeCmd, "r");
8723 if(fp)
8724 {
8725 pclose(fp);
8726 }
8727 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8728 if(fp)
8729 {
8730 for(count =0 ; count < wifi_count ;count++)
8731 {
8732 fgets(str, MAX_BUF_SIZE, fp);
8733 signalstrength = atoi(str);
8734 temp[count].cli_RSSI = signalstrength;
8735 }
8736 pclose(fp);
8737 }
8738
8739
8740 //LastDataDownlinkRate
8741 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8742 fp = popen(pipeCmd, "r");
8743 if (fp)
8744 {
8745 pclose(fp);
8746 }
8747 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8748 if (fp)
8749 {
8750 for (count = 0; count < wifi_count; count++)
8751 {
8752 fgets(str, MAX_BUF_SIZE, fp);
8753 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8754 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8755 }
8756 pclose(fp);
8757 }
8758
8759 //LastDataUplinkRate
8760 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8761 fp = popen(pipeCmd, "r");
8762 if (fp)
8763 {
8764 pclose(fp);
8765 }
8766 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8767 if (fp)
8768 {
8769 for (count = 0; count < wifi_count; count++)
8770 {
8771 fgets(str, MAX_BUF_SIZE, fp);
8772 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8773 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8774 }
8775 pclose(fp);
8776 }
8777 }
8778 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8779 return RETURN_OK;
8780
8781}
8782
8783INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8784{
8785#if 0
8786 /*char buf[1024] = {0};
8787 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8788 _syscmd(cmd, buf, sizeof(buf));*/
8789
8790 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8791 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8792 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8793 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8794
8795 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.
8796 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].
8797 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].
8798 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].
8799 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8800 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8801
8802 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8803 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8804 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8805 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.
8806 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.
8807 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.
8808 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.
8809 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.
8810 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.
8811 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.
8812 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8813#endif
8814
8815 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008816 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008817 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008818 char pipeCmd[128] = {0};
8819 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008820 wifi_ssidTrafficStats2_t *out = output_struct;
8821
developerce736392022-09-13 15:24:34 +08008822 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008823 if (!output_struct)
8824 return RETURN_ERR;
8825
developerce736392022-09-13 15:24:34 +08008826 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8827 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8828 GetInterfaceName(interface_name, HConf_file);
8829 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008830
developer06a01d92022-09-07 16:32:39 +08008831 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008832 if (fp == NULL) {
8833 fprintf(stderr, "%s: popen failed\n", __func__);
8834 return RETURN_ERR;
8835 }
8836 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008837
developerce736392022-09-13 15:24:34 +08008838 if (strlen(str) == 0) // interface not exist
8839 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008840
developerce736392022-09-13 15:24:34 +08008841 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8842 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008843 pclose(fp);
8844
developerce736392022-09-13 15:24:34 +08008845 memset(str, 0, sizeof(str));
8846 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008847 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008848 if (fp == NULL) {
8849 fprintf(stderr, "%s: popen failed\n", __func__);
8850 return RETURN_ERR;
8851 }
8852 fgets(str, sizeof(str), fp);
8853
8854 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8855 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008856 pclose(fp);
developerce736392022-09-13 15:24:34 +08008857
8858 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8859 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8860
8861 // Not supported
8862 output_struct->ssid_RetransCount = 0;
8863 output_struct->ssid_FailedRetransCount = 0;
8864 output_struct->ssid_RetryCount = 0;
8865 output_struct->ssid_MultipleRetryCount = 0;
8866 output_struct->ssid_ACKFailureCount = 0;
8867 output_struct->ssid_AggregatedPacketCount = 0;
8868
developer06a01d92022-09-07 16:32:39 +08008869 return RETURN_OK;
8870}
8871
8872//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).
8873INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8874{
8875 char output_val[16]={'\0'};
8876 char config_file[MAX_BUF_SIZE] = {0};
8877
8878 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8879 if (!output)
8880 return RETURN_ERR;
8881 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8882 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8883
8884 if( strcmp(output_val,"1") == 0 )
8885 *output = TRUE;
8886 else
8887 *output = FALSE;
8888 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8889
8890 return RETURN_OK;
8891}
8892
8893INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8894{
8895 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8896 char str[MAX_BUF_SIZE]={'\0'};
8897 char string[MAX_BUF_SIZE]={'\0'};
8898 char cmd[MAX_CMD_SIZE]={'\0'};
8899 char *ch;
8900 char config_file[MAX_BUF_SIZE] = {0};
8901 struct params params;
8902
8903 if(enable == TRUE)
8904 strcpy(string,"1");
8905 else
8906 strcpy(string,"0");
8907
8908 params.name = "ap_isolate";
8909 params.value = string;
8910
8911 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8912 wifi_hostapdWrite(config_file,&params,1);
8913 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8914
8915 return RETURN_OK;
8916}
8917
8918INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8919{
8920 if (NULL == output_dBm)
8921 return RETURN_ERR;
8922
8923 *output_dBm = 0;
8924 return RETURN_OK;
8925}
8926
8927INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8928{
8929 return RETURN_OK;
8930}
8931INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8932{
8933 return RETURN_OK;
8934}
8935INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8936{
8937 return RETURN_OK;
8938}
8939INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8940{
8941 return RETURN_OK;
8942}
8943INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8944{
8945 return RETURN_OK;
8946}
8947INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8948{
8949 char config_file[MAX_BUF_SIZE] = {0};
8950 struct params list;
8951
8952 list.name = "bss_transition";
8953 list.value = activate?"1":"0";
8954 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8955 wifi_hostapdWrite(config_file, &list, 1);
8956
8957 return RETURN_OK;
8958}
8959wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8960
8961void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8962{
8963 return;
8964}
8965
8966INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8967{
8968 // TODO Implement me!
8969 return RETURN_OK;
8970}
8971
8972INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8973{
developera3c68b92022-09-13 15:27:29 +08008974 char file_name[128] = {0};
8975 char buf[128] = {0};
8976 FILE *f = NULL;
8977
8978 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8979
8980 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8981 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8982 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8983 f = fopen(file_name, "w");
8984 if (f == NULL)
8985 return RETURN_ERR;
8986 // For mode == 0 is to disable filter, just don't write to the file.
8987 if (mode)
8988 fprintf(f, "%s", essid);
8989
8990 fclose(f);
8991 }
8992 } else { // special case, need to set AP's SSID as filter for each radio.
8993 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8994 f = fopen(file_name, "w");
8995 if (f == NULL)
8996 return RETURN_ERR;
8997
8998 // For mode == 0 is to disable filter, just don't write to the file.
8999 if (mode)
9000 fprintf(f, "%s", essid);
9001
9002 fclose(f);
9003 }
9004
9005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009006 return RETURN_OK;
9007}
9008
9009INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9010{
9011 // TODO Implement me!
9012 //Apply wifi_pushRadioChannel() instantly
9013 return RETURN_ERR;
9014}
9015
9016INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9017{
9018 // TODO Implement me!
9019 return RETURN_OK;
9020}
9021
9022#ifdef HAL_NETLINK_IMPL
9023static int tidStats_callback(struct nl_msg *msg, void *arg) {
9024 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9025 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9026 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9027 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9028 int rem , tid_index = 0;
9029
9030 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9031 wifi_associated_dev_tid_entry_t *stats_entry;
9032
9033 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9034 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9035 };
9036 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9037 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9038 };
9039
9040 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9041 genlmsg_attrlen(gnlh, 0), NULL);
9042
9043
9044 if (!tb[NL80211_ATTR_STA_INFO]) {
9045 fprintf(stderr, "station stats missing!\n");
9046 return NL_SKIP;
9047 }
9048
9049 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9050 tb[NL80211_ATTR_STA_INFO],
9051 stats_policy)) {
9052 fprintf(stderr, "failed to parse nested attributes!\n");
9053 return NL_SKIP;
9054 }
9055
9056 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9057 {
9058 stats_entry = &out->tid_array[tid_index];
9059
9060 stats_entry->tid = tid_index;
9061 stats_entry->ac = _tid_ac_index_get[tid_index];
9062
9063 if(sinfo[NL80211_STA_INFO_TID_STATS])
9064 {
9065 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9066 printf("failed to parse nested stats attributes!");
9067 return NL_SKIP;
9068 }
9069 }
9070 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9071 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9072
9073 if(tid_index < (PS_MAX_TID - 1))
9074 tid_index++;
9075 }
9076 //ToDo: sum_time_ms, ewma_time_ms
9077 return NL_SKIP;
9078}
9079#endif
9080
9081INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9082{
9083#ifdef HAL_NETLINK_IMPL
9084 Netlink nl;
9085 char if_name[10];
9086
9087 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9088
9089 nl.id = initSock80211(&nl);
9090
9091 if (nl.id < 0) {
9092 fprintf(stderr, "Error initializing netlink \n");
9093 return -1;
9094 }
9095
9096 struct nl_msg* msg = nlmsg_alloc();
9097
9098 if (!msg) {
9099 fprintf(stderr, "Failed to allocate netlink message.\n");
9100 nlfree(&nl);
9101 return -2;
9102 }
9103
9104 genlmsg_put(msg,
9105 NL_AUTO_PORT,
9106 NL_AUTO_SEQ,
9107 nl.id,
9108 0,
9109 0,
9110 NL80211_CMD_GET_STATION,
9111 0);
9112
9113 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9114 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9115 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9116 nl_send_auto(nl.socket, msg);
9117 nl_recvmsgs(nl.socket, nl.cb);
9118 nlmsg_free(msg);
9119 nlfree(&nl);
9120 return RETURN_OK;
9121#else
9122//iw implementation
9123#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9124#define TOTAL_MAX_LINES 50
9125
9126 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9127 char if_name[10];
9128 FILE *fp=NULL;
9129 char pipeCmd[1024]= {'\0'};
9130 int lines,tid_index=0;
9131 char mac_addr[20] = {'\0'};
9132
9133 wifi_associated_dev_tid_entry_t *stats_entry;
9134
9135 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9136 strcpy(mac_addr,clientMacAddress);
9137
9138 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9139 fp= popen(pipeCmd,"r");
9140 if(fp == NULL)
9141 {
9142 perror("popen for station dump failed\n");
9143 return RETURN_ERR;
9144 }
9145 pclose(fp);
9146
9147 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9148 fp=popen(pipeCmd,"r");
9149 if(fp == NULL)
9150 {
9151 perror("popen for grep station failed\n");
9152 return RETURN_ERR;
9153 }
9154 else if(fgets(buf,sizeof(buf),fp) != NULL)
9155 lines=atoi(buf);
9156 else
9157 {
9158 pclose(fp);
9159 fprintf(stderr,"No devices are connected \n");
9160 return RETURN_ERR;
9161 }
9162 pclose(fp);
9163
9164 if(lines == 1)
9165 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9166
9167 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9168 {
9169 stats_entry = &tid_stats->tid_array[tid_index];
9170 stats_entry->tid = tid_index;
9171
9172 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);
9173
9174 fp=popen(pipeCmd,"r");
9175 if(fp ==NULL)
9176 {
9177 perror("Failed to read from tid file \n");
9178 return RETURN_ERR;
9179 }
9180 else if(fgets(buf,sizeof(buf),fp) != NULL)
9181 stats_entry->num_msdus = atol(buf);
9182
9183 pclose(fp);
9184 stats_entry->ac = _tid_ac_index_get[tid_index];
9185// TODO:
9186// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9187// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9188 }
9189 return RETURN_OK;
9190#endif
9191}
9192
9193
9194INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9195{
developer615510b2022-09-27 10:14:35 +08009196 char cmd[128]={0};
9197 char buf[128]={0};
9198 int freq = 0;
9199
9200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9201
9202 // full mode is used to scan all channels.
9203 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9204 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9205 ieee80211_channel_to_frequency(chan_list[0], &freq);
9206
9207 if (freq)
9208 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9209 else
9210 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9211
9212 _syscmd(cmd, buf, sizeof(buf));
9213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9214
developer06a01d92022-09-07 16:32:39 +08009215 return RETURN_OK;
9216}
9217
9218
9219INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9220{
9221 // TODO Implement me!
9222 return RETURN_ERR;
9223}
9224
9225INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9226{
9227 // TODO Implement me!
9228 return RETURN_ERR;
9229}
9230
9231INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9232{
9233 // TODO Implement me!
9234 return RETURN_ERR;
9235}
9236
9237INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9238{
9239 // TODO Implement me!
9240 return RETURN_ERR;
9241}
9242
9243INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9244{
9245 // TODO Implement me!
9246 return RETURN_ERR;
9247}
9248
9249INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9250{
9251 // TODO Implement me!
9252 return RETURN_ERR;
9253}
9254
9255INT wifi_steering_eventUnregister(void)
9256{
9257 // TODO Implement me!
9258 return RETURN_ERR;
9259}
9260
9261INT wifi_delApAclDevices(INT apIndex)
9262{
9263#if 0
9264 char cmd[MAX_BUF_SIZE] = {0};
9265 char buf[MAX_BUF_SIZE] = {0};
9266
9267 /* Not reset proof solution */
9268 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9269 if(_syscmd(cmd,buf,sizeof(buf)))
9270 return RETURN_ERR;
9271#endif
developere6aafda2022-09-13 14:59:28 +08009272 char cmd[MAX_CMD_SIZE]={0};
9273 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009274
developere6aafda2022-09-13 14:59:28 +08009275 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9276 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9277 if(_syscmd(cmd, buf, sizeof(buf)))
9278 return RETURN_ERR;
9279 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009280
9281 return RETURN_OK;
9282}
9283
9284#ifdef HAL_NETLINK_IMPL
9285static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9286 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9287 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9288 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9289 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9290 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9291 char mac_addr[20],dev[20];
9292
9293 nla_parse(tb,
9294 NL80211_ATTR_MAX,
9295 genlmsg_attrdata(gnlh, 0),
9296 genlmsg_attrlen(gnlh, 0),
9297 NULL);
9298
9299 if(!tb[NL80211_ATTR_STA_INFO]) {
9300 fprintf(stderr, "sta stats missing!\n");
9301 return NL_SKIP;
9302 }
9303
9304 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9305 fprintf(stderr, "failed to parse nested attributes!\n");
9306 return NL_SKIP;
9307 }
9308 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9309
9310 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9311
9312 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9313 fprintf(stderr, "failed to parse nested rate attributes!");
9314 return NL_SKIP;
9315 }
9316
9317 if(sinfo[NL80211_STA_INFO_TID_STATS])
9318 {
9319 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9320 printf("failed to parse nested stats attributes!");
9321 return NL_SKIP;
9322 }
9323 }
9324
9325 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9326 {
9327 printf("Type is VHT\n");
9328 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9329 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9330
9331 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9332 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9333 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9334 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9335 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9336 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9337 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9338 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9339 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9340 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9341 }
9342 else
9343 {
9344 printf(" OFDM or CCK \n");
9345 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9346 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9347 }
9348
9349 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9350 if(rinfo[NL80211_RATE_INFO_MCS])
9351 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9352 }
9353 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9354 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9355 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9356 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9357
9358 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9359 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9360
9361 if (sinfo[NL80211_STA_INFO_SIGNAL])
9362 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9363 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9364 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9365 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9366 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9367 //rssi_array need to be filled
9368 return NL_SKIP;
9369}
9370#endif
9371
9372INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9373{
9374#ifdef HAL_NETLINK_IMPL
9375 Netlink nl;
9376 char if_name[10];
9377
9378 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9379
9380 if (*output_array_size <= 0)
9381 return RETURN_OK;
9382
9383 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9384 nl.id = initSock80211(&nl);
9385
9386 if (nl.id < 0) {
9387 fprintf(stderr, "Error initializing netlink \n");
9388 return 0;
9389 }
9390
9391 struct nl_msg* msg = nlmsg_alloc();
9392
9393 if (!msg) {
9394 fprintf(stderr, "Failed to allocate netlink message.\n");
9395 nlfree(&nl);
9396 return 0;
9397 }
9398
9399 genlmsg_put(msg,
9400 NL_AUTO_PORT,
9401 NL_AUTO_SEQ,
9402 nl.id,
9403 0,
9404 0,
9405 NL80211_CMD_GET_STATION,
9406 0);
9407
9408 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9409 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9410 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9411 nl_send_auto(nl.socket, msg);
9412 nl_recvmsgs(nl.socket, nl.cb);
9413 nlmsg_free(msg);
9414 nlfree(&nl);
9415 return RETURN_OK;
9416#else
9417 //TODO Implement me
9418 return RETURN_OK;
9419#endif
9420}
9421
9422#ifdef HAL_NETLINK_IMPL
9423static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9424 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9425 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9426 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9427 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9428 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9429 char mac_addr[20],dev[20];
9430
9431 nla_parse(tb,
9432 NL80211_ATTR_MAX,
9433 genlmsg_attrdata(gnlh, 0),
9434 genlmsg_attrlen(gnlh, 0),
9435 NULL);
9436
9437 if(!tb[NL80211_ATTR_STA_INFO]) {
9438 fprintf(stderr, "sta stats missing!\n");
9439 return NL_SKIP;
9440 }
9441
9442 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9443 fprintf(stderr, "failed to parse nested attributes!\n");
9444 return NL_SKIP;
9445 }
9446
9447 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9448
9449 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9450
9451 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9452 fprintf(stderr, "failed to parse nested rate attributes!");
9453 return NL_SKIP;
9454 }
9455
9456 if(sinfo[NL80211_STA_INFO_TID_STATS])
9457 {
9458 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9459 printf("failed to parse nested stats attributes!");
9460 return NL_SKIP;
9461 }
9462 }
9463 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9464 {
9465 printf("Type is VHT\n");
9466 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9467 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9468
9469 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9470 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9471 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9472 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9473 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9474 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9475 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9476 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9477 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9478 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9479 }
9480 else
9481 {
9482 printf(" OFDM or CCK \n");
9483 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9484 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9485 }
9486
9487 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9488 if(rinfo[NL80211_RATE_INFO_MCS])
9489 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9490 }
9491
9492 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9493 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9494 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9495 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9496
9497 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9498 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9499 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9500
9501 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9502 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9503
9504 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9505 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9506
9507 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9508 ((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]);
9509
9510 return NL_SKIP;
9511}
9512#endif
9513
9514INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9515{
9516#ifdef HAL_NETLINK_IMPL
9517 Netlink nl;
9518 char if_name[10];
9519
9520 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9521
9522 if (*output_array_size <= 0)
9523 return RETURN_OK;
9524
9525 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9526
9527 nl.id = initSock80211(&nl);
9528
9529 if(nl.id < 0) {
9530 fprintf(stderr, "Error initializing netlink \n");
9531 return 0;
9532 }
9533
9534 struct nl_msg* msg = nlmsg_alloc();
9535
9536 if(!msg) {
9537 fprintf(stderr, "Failed to allocate netlink message.\n");
9538 nlfree(&nl);
9539 return 0;
9540 }
9541
9542 genlmsg_put(msg,
9543 NL_AUTO_PORT,
9544 NL_AUTO_SEQ,
9545 nl.id,
9546 0,
9547 0,
9548 NL80211_CMD_GET_STATION,
9549 0);
9550
9551 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9552 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9553 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9554 nl_send_auto(nl.socket, msg);
9555 nl_recvmsgs(nl.socket, nl.cb);
9556 nlmsg_free(msg);
9557 nlfree(&nl);
9558 return RETURN_OK;
9559#else
9560 //TODO Implement me
9561 return RETURN_OK;
9562#endif
9563}
9564
9565INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9566{
9567 // TODO Implement me!
9568 char buf[MAX_BUF_SIZE] = {0};
9569 char config_file[MAX_BUF_SIZE] = {0};
9570
9571 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9572 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9573 *activate = (strncmp("1",buf,1) == 0);
9574
9575 return RETURN_OK;
9576}
9577
9578INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9579{
9580 char config_file[MAX_BUF_SIZE] = {0};
9581 struct params list;
9582
9583 list.name = "rrm_neighbor_report";
9584 list.value = activate?"1":"0";
9585 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9586 wifi_hostapdWrite(config_file, &list, 1);
9587
9588 return RETURN_OK;
9589}
9590
9591INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9592{
9593 char buf[32] = {0};
9594 char config_file[MAX_BUF_SIZE] = {0};
9595
9596 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9597 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9598 *activate = (strncmp("1",buf,1) == 0);
9599
9600 return RETURN_OK;
9601}
9602#undef HAL_NETLINK_IMPL
9603#ifdef HAL_NETLINK_IMPL
9604static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9605 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9606 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9607 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9608 char dev[20];
9609 int freq =0 ;
9610 static int i=0;
9611
9612 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9613
9614 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9615 };
9616
9617 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9618
9619 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9620
9621 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9622 fprintf(stderr, "survey data missing!\n");
9623 return NL_SKIP;
9624 }
9625
9626 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9627 {
9628 fprintf(stderr, "failed to parse nested attributes!\n");
9629 return NL_SKIP;
9630 }
9631
9632
9633 if(out[0].array_size == 1 )
9634 {
9635 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9636 {
9637 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9638 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9639 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9640
9641 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9642 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9643 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9644 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9645 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9646 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9647 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9648 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9649 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9650 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9651 if (sinfo[NL80211_SURVEY_INFO_TIME])
9652 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9653 return NL_STOP;
9654 }
9655 }
9656 else
9657 {
9658 if ( i <= out[0].array_size )
9659 {
9660 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9661 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9662 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9663
9664 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9665 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9666 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9667 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9668 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9669 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9670 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9671 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9672 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9673 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9674 if (sinfo[NL80211_SURVEY_INFO_TIME])
9675 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9676 }
9677 }
9678
9679 i++;
9680 return NL_SKIP;
9681}
9682#endif
9683
9684static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9685{
9686 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9687 FILE *fp;
9688
9689 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9690 {
9691 printf("Creating Frequency-Channel Map\n");
9692 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9693 }
9694 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9695 if((fp = popen(command, "r")))
9696 {
9697 fgets(output, sizeof(output), fp);
9698 *freqMHz = atoi(output);
9699 fclose(fp);
9700 }
9701
9702 return 0;
9703}
9704
9705static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9706{
9707 int freqMHz = -1;
9708 char cmd[MAX_CMD_SIZE] = {'\0'};
9709
9710 ieee80211_channel_to_frequency(channel, &freqMHz);
9711 if (freqMHz == -1) {
9712 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9713 return -1;
9714 }
9715
9716 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9717 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9718 radioIndex, freqMHz);
9719 return -1;
9720 }
9721
9722 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9723 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9724 return -1;
9725 }
9726
9727 return 0;
9728}
9729
9730static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9731{
9732 const char *ptr = buf;
9733 char *key = NULL;
9734 char *val = NULL;
9735 char line[256] = { '\0' };
9736
9737 while (ptr = get_line_from_str_buf(ptr, line)) {
9738 if (strstr(line, "Frequency")) continue;
9739
9740 key = strtok(line, ":");
9741 val = strtok(NULL, " ");
9742 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9743
9744 if (!strcmp(key, "noise")) {
9745 sscanf(val, "%d", &stats->ch_noise);
9746 if (stats->ch_noise == 0) {
9747 // Workaround for missing noise information.
9748 // Assume -95 for 2.4G and -103 for 5G
9749 if (radioIndex == 0) stats->ch_noise = -95;
9750 if (radioIndex == 1) stats->ch_noise = -103;
9751 }
9752 }
9753 else if (!strcmp(key, "channel active time")) {
9754 sscanf(val, "%llu", &stats->ch_utilization_total);
9755 }
9756 else if (!strcmp(key, "channel busy time")) {
9757 sscanf(val, "%llu", &stats->ch_utilization_busy);
9758 }
9759 else if (!strcmp(key, "channel receive time")) {
9760 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9761 }
9762 else if (!strcmp(key, "channel transmit time")) {
9763 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9764 }
9765 };
9766
9767 return 0;
9768}
9769
9770INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9771{
9772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9773#ifdef HAL_NETLINK_IMPL
9774 Netlink nl;
9775 wifi_channelStats_t_loc local[array_size];
9776 char if_name[10];
9777
9778 local[0].array_size = array_size;
9779
9780 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9781
9782 nl.id = initSock80211(&nl);
9783
9784 if (nl.id < 0) {
9785 fprintf(stderr, "Error initializing netlink \n");
9786 return -1;
9787 }
9788
9789 struct nl_msg* msg = nlmsg_alloc();
9790
9791 if (!msg) {
9792 fprintf(stderr, "Failed to allocate netlink message.\n");
9793 nlfree(&nl);
9794 return -2;
9795 }
9796
9797 genlmsg_put(msg,
9798 NL_AUTO_PORT,
9799 NL_AUTO_SEQ,
9800 nl.id,
9801 0,
9802 NLM_F_DUMP,
9803 NL80211_CMD_GET_SURVEY,
9804 0);
9805
9806 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9807 nl_send_auto(nl.socket, msg);
9808 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9809 nl_recvmsgs(nl.socket, nl.cb);
9810 nlmsg_free(msg);
9811 nlfree(&nl);
9812 //Copying the Values
9813 for(int i=0;i<array_size;i++)
9814 {
9815 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9816 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9817 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9818 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9819 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9820 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9821 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9822 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9823 }
9824#else
9825 ULONG channel = 0;
9826 int i;
9827 int number_of_channels = array_size;
9828 char buf[512];
9829 INT ret;
9830 wifi_channelStats_t tmp_stats;
9831
9832 if (number_of_channels == 0) {
9833 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9834 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9835 return RETURN_ERR;
9836 }
9837 number_of_channels = 1;
9838 input_output_channelStats_array[0].ch_number = channel;
9839 }
9840
9841 for (i = 0; i < number_of_channels; i++) {
9842
9843 input_output_channelStats_array[i].ch_noise = 0;
9844 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9845 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9846 input_output_channelStats_array[i].ch_utilization_busy = 0;
9847 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9848 input_output_channelStats_array[i].ch_utilization_total = 0;
9849
9850 memset(buf, 0, sizeof(buf));
9851 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9852 return RETURN_ERR;
9853 }
9854 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9855 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9856 return RETURN_ERR;
9857 }
9858
9859 // XXX: fake missing 'self' counter which is not available in iw survey output
9860 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9861 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9862
9863 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9864 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9865 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9866 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9867 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9868
9869 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",
9870 __func__,
9871 input_output_channelStats_array[i].ch_number,
9872 input_output_channelStats_array[i].ch_noise,
9873 input_output_channelStats_array[i].ch_utilization_total,
9874 input_output_channelStats_array[i].ch_utilization_busy,
9875 input_output_channelStats_array[i].ch_utilization_busy_rx,
9876 input_output_channelStats_array[i].ch_utilization_busy_tx,
9877 input_output_channelStats_array[i].ch_utilization_busy_self,
9878 input_output_channelStats_array[i].ch_utilization_busy_ext);
9879 }
9880#endif
9881 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9882 return RETURN_OK;
9883}
9884#define HAL_NETLINK_IMPL
9885
9886/* Hostapd events */
9887
9888#ifndef container_of
9889#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9890#define container_of(ptr, type, member) \
9891 ((type *)((char *)ptr - offset_of(type, member)))
9892#endif /* container_of */
9893
9894struct ctrl {
9895 char sockpath[128];
9896 char sockdir[128];
9897 char bss[IFNAMSIZ];
9898 char reply[4096];
9899 int ssid_index;
9900 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9901 void (*overrun)(struct ctrl *ctrl);
9902 struct wpa_ctrl *wpa;
9903 unsigned int ovfl;
9904 size_t reply_len;
9905 int initialized;
9906 ev_timer retry;
9907 ev_timer watchdog;
9908 ev_stat stat;
9909 ev_io io;
9910};
9911static wifi_newApAssociatedDevice_callback clients_connect_cb;
9912static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9913static struct ctrl wpa_ctrl[MAX_APS];
9914static int initialized;
9915
9916static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9917{
9918 char cbuf[256] = {};
9919 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9920 struct cmsghdr *cmsg;
9921 unsigned int ovfl = ctrl->ovfl;
9922 unsigned int drop;
9923
9924 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9925 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9926 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9927 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9928
9929 drop = ovfl - ctrl->ovfl;
9930 ctrl->ovfl = ovfl;
9931
9932 return drop;
9933}
9934
9935static void ctrl_close(struct ctrl *ctrl)
9936{
9937 if (ctrl->io.cb)
9938 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9939 if (ctrl->retry.cb)
9940 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9941 if (!ctrl->wpa)
9942 return;
9943
9944 wpa_ctrl_detach(ctrl->wpa);
9945 wpa_ctrl_close(ctrl->wpa);
9946 ctrl->wpa = NULL;
9947 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9948}
9949
9950static void ctrl_process(struct ctrl *ctrl)
9951{
9952 const char *str;
9953 int drops;
9954 int level;
9955 int err;
9956
9957 /* Example events:
9958 *
9959 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9960 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9961 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9962 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9963 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9964 */
9965 if (!(str = index(ctrl->reply, '>')))
9966 return;
9967 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9968 return;
9969
9970 str++;
9971
9972 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9973 if (!(str = index(ctrl->reply, ' ')))
9974 return;
9975 wifi_associated_dev_t sta;
9976 memset(&sta, 0, sizeof(sta));
9977
9978 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9979 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9980 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9981
9982 sta.cli_Active=true;
9983
9984 (clients_connect_cb)(ctrl->ssid_index, &sta);
9985 goto handled;
9986 }
9987
9988 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9989 if (!(str = index(ctrl->reply, ' ')))
9990 return;
9991
9992 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9993 goto handled;
9994 }
9995
9996 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9997 printf("CTRL_WPA: handle TERMINATING event\n");
9998 goto retry;
9999 }
10000
10001 if (strncmp("AP-DISABLED", str, 11) == 0) {
10002 printf("CTRL_WPA: handle AP-DISABLED\n");
10003 goto retry;
10004 }
10005
10006 printf("Event not supported!!\n");
10007
10008handled:
10009
10010 if ((drops = ctrl_get_drops(ctrl))) {
10011 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10012 if (ctrl->overrun)
10013 ctrl->overrun(ctrl);
10014 }
10015
10016 return;
10017
10018retry:
10019 printf("WPA_CTRL: closing\n");
10020 ctrl_close(ctrl);
10021 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10022 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10023}
10024
10025static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10026{
10027 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10028 int err;
10029
10030 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10031 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10032 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10033 ctrl->reply[ctrl->reply_len] = 0;
10034 if (err < 0) {
10035 if (errno == EAGAIN || errno == EWOULDBLOCK)
10036 return;
10037 ctrl_close(ctrl);
10038 ev_timer_again(EV_A_ &ctrl->retry);
10039 return;
10040 }
10041
10042 ctrl_process(ctrl);
10043}
10044
10045static int ctrl_open(struct ctrl *ctrl)
10046{
10047 int fd;
10048
10049 if (ctrl->wpa)
10050 return 0;
10051
10052 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10053 if (!ctrl->wpa)
10054 goto err;
10055
10056 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10057 goto err_close;
10058
10059 fd = wpa_ctrl_get_fd(ctrl->wpa);
10060 if (fd < 0)
10061 goto err_detach;
10062
10063 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10064 goto err_detach;
10065
10066 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10067 ev_io_start(EV_DEFAULT_ &ctrl->io);
10068
10069 return 0;
10070
10071err_detach:
10072 wpa_ctrl_detach(ctrl->wpa);
10073err_close:
10074 wpa_ctrl_close(ctrl->wpa);
10075err:
10076 ctrl->wpa = NULL;
10077 return -1;
10078}
10079
10080static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10081{
10082 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10083
10084 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10085 ctrl_open(ctrl);
10086}
10087
10088static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10089{
10090 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10091
10092 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10093 if (ctrl_open(ctrl) == 0) {
10094 printf("WPA_CTRL: retry successful\n");
10095 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10096 }
10097}
10098
10099int ctrl_enable(struct ctrl *ctrl)
10100{
10101 if (ctrl->wpa)
10102 return 0;
10103
10104 if (!ctrl->stat.cb) {
10105 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10106 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10107 }
10108
10109 if (!ctrl->retry.cb) {
10110 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10111 }
10112
10113 return ctrl_open(ctrl);
10114}
10115
10116static void
10117ctrl_msg_cb(char *buf, size_t len)
10118{
10119 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10120
10121 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10122 ctrl_process(ctrl);
10123}
10124
10125static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10126{
10127 int err;
10128
10129 if (!ctrl->wpa)
10130 return -1;
10131 if (*reply_len < 2)
10132 return -1;
10133
10134 (*reply_len)--;
10135 ctrl->reply_len = sizeof(ctrl->reply);
10136 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10137 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10138 if (err < 0)
10139 return err;
10140
10141 if (ctrl->reply_len > *reply_len)
10142 ctrl->reply_len = *reply_len;
10143
10144 *reply_len = ctrl->reply_len;
10145 memcpy(reply, ctrl->reply, *reply_len);
10146 reply[*reply_len - 1] = 0;
10147 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10148 return 0;
10149}
10150
10151static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10152{
10153 const char *pong = "PONG";
10154 const char *ping = "PING";
10155 char reply[1024];
10156 size_t len = sizeof(reply);
10157 int err;
10158 ULONG s, snum;
10159 INT ret;
10160 BOOL status;
10161
10162 printf("WPA_CTRL: watchdog cb\n");
10163
10164 ret = wifi_getSSIDNumberOfEntries(&snum);
10165 if (ret != RETURN_OK) {
10166 printf("%s: failed to get SSID count", __func__);
10167 return;
10168 }
10169
10170 if (snum > MAX_APS) {
10171 printf("more ssid than supported! %lu\n", snum);
10172 return;
10173 }
10174
10175 for (s = 0; s < snum; s++) {
10176 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10177 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10178 continue;
10179 }
10180 if (status == false) continue;
10181
10182 memset(reply, 0, sizeof(reply));
10183 len = sizeof(reply);
10184 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10185 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10186 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10187 continue;
10188
10189 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10190 ctrl_close(&wpa_ctrl[s]);
10191 printf("WPA_CTRL: ev_timer_again %d\n", s);
10192 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10193 }
10194}
10195
10196static int init_wpa()
10197{
10198 int ret = 0, i = 0;
10199 ULONG s, snum;
10200
10201 ret = wifi_getSSIDNumberOfEntries(&snum);
10202 if (ret != RETURN_OK) {
10203 printf("%s: failed to get SSID count", __func__);
10204 return RETURN_ERR;
10205 }
10206
10207 if (snum > MAX_APS) {
10208 printf("more ssid than supported! %lu\n", snum);
10209 return RETURN_ERR;
10210 }
10211
10212 for (s = 0; s < snum; s++) {
10213 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10214 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10215 wpa_ctrl[s].ssid_index = s;
10216 ctrl_enable(&wpa_ctrl[s]);
10217 }
10218
10219 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10220 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10221
10222 initialized = 1;
10223 printf("WPA_CTRL: initialized\n");
10224
10225 return RETURN_OK;
10226}
10227
10228void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10229{
10230 clients_connect_cb = callback_proc;
10231 if (!initialized)
10232 init_wpa();
10233}
10234
10235void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10236{
10237 clients_disconnect_cb = callback_proc;
10238 if (!initialized)
10239 init_wpa();
10240}
10241
10242INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10243{
10244 // TODO Implement me!
10245 return RETURN_ERR;
10246}
10247
10248INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10249{
10250 // TODO Implement me!
10251 return RETURN_ERR;
10252}
10253
10254INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10255{
10256 int i;
10257 char cmd[256];
10258 char channel_numbers_buf[256];
10259 char dfs_state_buf[256];
10260 char line[256];
10261 const char *ptr;
10262
10263 memset(cmd, 0, sizeof(cmd));
10264 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10265 memset(line, 0, sizeof(line));
10266 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10267 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10268
10269 if (radioIndex == 0) { // 2.4G - all allowed
10270 if (outputMapSize < 11) {
10271 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10272 return RETURN_ERR;
10273 }
10274
10275 for (i = 0; i < 11; i++) {
10276 outputMap[i].ch_number = i + 1;
10277 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10278 }
10279
10280 return RETURN_OK;
10281 }
10282
10283 if (radioIndex == 1) { // 5G
10284// Example output of iw list:
10285//
10286// Frequencies:
10287// * 5180 MHz [36] (17.0 dBm)
10288// * 5200 MHz [40] (17.0 dBm)
10289// * 5220 MHz [44] (17.0 dBm)
10290// * 5240 MHz [48] (17.0 dBm)
10291// * 5260 MHz [52] (23.0 dBm) (radar detection)
10292// DFS state: usable (for 78930 sec)
10293// DFS CAC time: 60000 ms
10294// * 5280 MHz [56] (23.0 dBm) (radar detection)
10295// DFS state: usable (for 78930 sec)
10296// DFS CAC time: 60000 ms
10297// * 5300 MHz [60] (23.0 dBm) (radar detection)
10298// DFS state: usable (for 78930 sec)
10299// DFS CAC time: 60000 ms
10300// * 5320 MHz [64] (23.0 dBm) (radar detection)
10301// DFS state: usable (for 78930 sec)
10302// DFS CAC time: 60000 ms
10303// * 5500 MHz [100] (disabled)
10304// * 5520 MHz [104] (disabled)
10305// * 5540 MHz [108] (disabled)
10306// * 5560 MHz [112] (disabled)
10307//
10308// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10309 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10310 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10311 return RETURN_ERR;
10312 }
10313
10314 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10315 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10316 return RETURN_ERR;
10317 }
10318
10319 ptr = channel_numbers_buf;
10320 i = 0;
10321 while (ptr = get_line_from_str_buf(ptr, line)) {
10322 if (i >= outputMapSize) {
10323 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10324 return RETURN_ERR;
10325 }
10326 sscanf(line, "%d", &outputMap[i].ch_number);
10327
10328 memset(cmd, 0, sizeof(cmd));
10329 // Below command should fetch string for DFS state (usable, available or unavailable)
10330 // Example line: "DFS state: usable (for 78930 sec)"
10331 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) {
10332 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10333 return RETURN_ERR;
10334 }
10335
10336 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10337 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10338 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10339 return RETURN_ERR;
10340 }
10341
10342 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10343
10344 if (!strcmp(dfs_state_buf, "usable")) {
10345 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10346 } else if (!strcmp(dfs_state_buf, "available")) {
10347 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10348 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10349 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10350 } else {
10351 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10352 }
10353 i++;
10354 }
10355
10356 return RETURN_OK;
10357 }
10358
10359 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10360 return RETURN_ERR;
10361}
10362
10363INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10364{
10365 // TODO Implement me!
10366 return RETURN_ERR;
10367}
10368
10369INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10370{
10371 return RETURN_OK;
10372}
10373
10374INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10375{
10376 // TODO Implement me!
10377 return RETURN_ERR;
10378}
10379
10380INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10381{
10382 // TODO API refrence Implementaion is present on RPI hal
10383 return RETURN_ERR;
10384}
10385
10386INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10387{
developera5005b62022-09-13 15:43:35 +080010388 char cmd[128]={'\0'};
10389 char buf[128]={'\0'};
10390 char *support;
10391 int maximum_tx = 0, current_tx = 0;
10392
10393 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10394 if(txpwr_pcntg == NULL)
10395 return RETURN_ERR;
10396
10397 // Get the maximum tx power of the device
10398 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10399 _syscmd(cmd, buf, sizeof(buf));
10400 maximum_tx = strtol(buf, NULL, 10);
10401
10402 // Get the current tx power
10403 memset(cmd, 0, sizeof(cmd));
10404 memset(buf, 0, sizeof(buf));
10405 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10406 _syscmd(cmd, buf, sizeof(buf));
10407 current_tx = strtol(buf, NULL, 10);
10408
10409 // Get the power supported list and find the current power percentage in supported list
10410 memset(buf, 0, sizeof(buf));
10411 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10412 support = strtok(buf, ",");
10413 while(true)
10414 {
10415 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10416 *txpwr_pcntg = 0;
10417 wifi_dbg_printf("current power is not in supported list\n");
10418 return RETURN_ERR;
10419 }
10420 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10421 if (tmp == current_tx) {
10422 *txpwr_pcntg = strtol(support, NULL, 10);
10423 break;
10424 }
10425 support = strtok(NULL, ",");
10426 }
10427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010428 return RETURN_OK;
10429}
10430
10431INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10432{
developer58599c22022-09-13 16:40:34 +080010433 // TODO precac feature.
10434 struct params params = {0};
10435 char config_file[128] = {0};
10436
10437 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10438
10439 params.name = "enable_background_radar";
10440 params.value = enable?"1":"0";
10441 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10442 wifi_hostapdWrite(config_file, &params, 1);
10443 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10444
10445 /* TODO precac feature */
10446
10447 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10448 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010449}
10450
10451INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10452{
developer58599c22022-09-13 16:40:34 +080010453 char config_file[128] = {0};
10454 char buf[64] = {0};
10455
10456 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10457 if (NULL == enable || NULL == precac)
10458 return RETURN_ERR;
10459
10460 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10461 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10462 if (strncmp(enable, "1", 1) == 0)
10463 *enable = true;
10464 else
10465 *enable = false;
10466
10467 /* TODO precac feature */
10468
10469 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10470 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010471}
10472
10473INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10474{
developer58599c22022-09-13 16:40:34 +080010475 *supported = TRUE;
10476 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010477}
10478
developer3e6b1692022-09-30 18:04:05 +080010479INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10480{
10481 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10482 struct params params = {0};
10483 char config_file[64] = {0};
10484 char buf[64] = {0};
10485 unsigned int set_mu_type = 0;
10486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10487
10488 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10489 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10490
10491 if (strlen(buf) > 0)
10492 set_mu_type = strtol(buf, NULL, 10);
10493
10494 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10495 set_mu_type &= ~0x05; // unset bit 0, 2
10496 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10497 set_mu_type |= 0x01;
10498 set_mu_type &= ~0x04;
10499 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10500 set_mu_type &= ~0x01;
10501 set_mu_type |= 0x04;
10502 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10503 set_mu_type |= 0x05; // set bit 0, 2
10504 }
10505
10506 params.name = "hemu_onoff";
10507 sprintf(buf, "%u", set_mu_type);
10508 params.value = buf;
10509 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10510 wifi_hostapdWrite(config_file, &params, 1);
10511 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10512
10513 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10514 return RETURN_OK;
10515}
10516
10517INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10518{
10519 struct params params={0};
10520 char config_file[64] = {0};
10521 char buf[64] = {0};
10522 unsigned int get_mu_type = 0;
10523
10524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10525
10526 if (mu_type == NULL)
10527 return RETURN_ERR;
10528
10529 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10530 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10531 get_mu_type = strtol(buf, NULL, 10);
10532
10533 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10534 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10535 else if (get_mu_type & 0x04)
10536 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10537 else if (get_mu_type & 0x01)
10538 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10539 else
10540 *mu_type = WIFI_DL_MU_TYPE_NONE;
10541
10542 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10543 return RETURN_OK;
10544}
10545
10546INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10547{
10548 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10549 struct params params={0};
10550 char config_file[64] = {0};
10551 char buf[64] = {0};
10552 unsigned int set_mu_type = 0;
10553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10554
10555 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10556 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10557
10558 if (strlen(buf) > 0)
10559 set_mu_type = strtol(buf, NULL, 10);
10560
10561 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10562 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10563 set_mu_type &= ~0x0a;
10564 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10565 set_mu_type |= 0x02;
10566 set_mu_type &= ~0x08;
10567 }
10568
10569 params.name = "hemu_onoff";
10570 sprintf(buf, "%u", set_mu_type);
10571 params.value = buf;
10572 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10573 wifi_hostapdWrite(config_file, &params, 1);
10574 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10575
10576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10577 return RETURN_OK;
10578}
10579
10580INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10581{
10582 struct params params={0};
10583 char config_file[64] = {0};
10584 char buf[64] = {0};
10585 unsigned int get_mu_type = 0;
10586
10587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10588
10589 if (mu_type == NULL)
10590 return RETURN_ERR;
10591
10592 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10593 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10594
10595 get_mu_type = strtol(buf, NULL, 10);
10596 if (get_mu_type & 0x02)
10597 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10598 else
10599 *mu_type = WIFI_DL_MU_TYPE_NONE;
10600
10601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10602 return RETURN_OK;
10603}
10604
10605
developer454b9462022-09-13 15:29:16 +080010606INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10607{
10608 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010609 char buf[256] = {0};
10610 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010611 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010612 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010613 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010614 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010615
10616 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10617
developer254882b2022-09-30 17:12:31 +080010618 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010619 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10620 return RETURN_ERR;
10621 }
developer454b9462022-09-13 15:29:16 +080010622
developer254882b2022-09-30 17:12:31 +080010623 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010624 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010625
developer254882b2022-09-30 17:12:31 +080010626 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10627 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
10628 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
10629 _syscmd(cmd, buf, sizeof(buf));
10630 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10631 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10632 if (strstr(buf, "[SHORT-GI-") == NULL) {
10633 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
10634 _syscmd(cmd, buf, sizeof(buf));
10635 }
10636 if (band == band_5) {
10637 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10638 if (strstr(buf, "[SHORT-GI-") == NULL) {
10639 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
10640 _syscmd(cmd, buf, sizeof(buf));
10641 }
10642 }
10643 }
10644 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010645
developer254882b2022-09-30 17:12:31 +080010646 if (guard_interval == wifi_guard_interval_400)
10647 strcpy(GI, "0.4");
10648 else if (guard_interval == wifi_guard_interval_800)
10649 strcpy(GI, "0.8");
10650 else if (guard_interval == wifi_guard_interval_1600)
10651 strcpy(GI, "1.6");
10652 else if (guard_interval == wifi_guard_interval_3200)
10653 strcpy(GI, "3.2");
10654 else if (guard_interval == wifi_guard_interval_auto)
10655 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010656 // Record GI for get GI function
10657 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10658 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010659 if (f == NULL)
10660 return RETURN_ERR;
10661 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010662 fclose(f);
10663 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10664 return RETURN_OK;
10665}
10666
10667INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10668{
10669 char buf[32] = {0};
10670 char cmd[64] = {0};
10671
10672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10673
10674 if (guard_interval == NULL)
10675 return RETURN_ERR;
10676
10677 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10678 _syscmd(cmd, buf, sizeof(buf));
10679
10680 if (strncmp(buf, "0.4", 3) == 0)
10681 *guard_interval = wifi_guard_interval_400;
10682 else if (strncmp(buf, "0.8", 3) == 0)
10683 *guard_interval = wifi_guard_interval_800;
10684 else if (strncmp(buf, "1.6", 3) == 0)
10685 *guard_interval = wifi_guard_interval_1600;
10686 else if (strncmp(buf, "3.2", 3) == 0)
10687 *guard_interval = wifi_guard_interval_3200;
10688 else
10689 *guard_interval = wifi_guard_interval_auto;
10690
10691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10692 return RETURN_OK;
10693}
10694
developer3cc61d12022-09-13 16:36:05 +080010695INT wifi_setBSSColor(INT radio_index, UCHAR color)
10696{
10697 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10698 struct params params = {0};
10699 char config_file[128] = {0};
10700 char bss_color[4] ={0};
10701
10702 params.name = "he_bss_color";
10703 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10704 params.value = bss_color;
10705 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10706 wifi_hostapdWrite(config_file, &params, 1);
10707 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10708
10709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10710 return RETURN_OK;
10711}
10712
10713INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10714{
10715 char config_file[128] = {0};
10716 char buf[64] = {0};
10717 char temp_output[128] = {'\0'};
10718
10719 wifi_dbg_printf("\nFunc=%s\n", __func__);
10720 if (NULL == color)
10721 return RETURN_ERR;
10722
10723 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10724 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10725
10726 if(strlen(buf) > 0) {
10727 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10728 } else {
10729 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10730 }
10731
10732 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10733 wifi_dbg_printf("\noutput_string=%s\n", color);
10734
10735 return RETURN_OK;
10736}
10737
developer06a01d92022-09-07 16:32:39 +080010738/* multi-psk support */
10739INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10740{
10741 char cmd[256];
10742
10743 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10744 AP_PREFIX,
10745 apIndex,
10746 mac[0],
10747 mac[1],
10748 mac[2],
10749 mac[3],
10750 mac[4],
10751 mac[5]
10752 );
10753 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10754 _syscmd(cmd, key->wifi_keyId, 64);
10755
10756
10757 return RETURN_OK;
10758}
10759
10760INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10761{
10762 FILE *fd = NULL;
10763 char fname[100];
10764 char cmd[128] = {0};
10765 char out[64] = {0};
10766 wifi_key_multi_psk_t * key = NULL;
10767 if(keysNumber < 0)
10768 return RETURN_ERR;
10769
10770 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10771 fd = fopen(fname, "w");
10772 if (!fd) {
10773 return RETURN_ERR;
10774 }
10775 key= (wifi_key_multi_psk_t *) keys;
10776 for(int i=0; i<keysNumber; ++i, key++) {
10777 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10778 }
10779 fclose(fd);
10780
10781 //reload file
10782 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10783 _syscmd(cmd, out, 64);
10784 return RETURN_OK;
10785}
10786
10787INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10788{
10789 FILE *fd = NULL;
10790 char fname[100];
10791 char * line = NULL;
10792 char * pos = NULL;
10793 size_t len = 0;
10794 ssize_t read = 0;
10795 INT ret = RETURN_OK;
10796 wifi_key_multi_psk_t *keys_it = NULL;
10797
10798 if (keysNumber < 1) {
10799 return RETURN_ERR;
10800 }
10801
10802 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10803 fd = fopen(fname, "r");
10804 if (!fd) {
10805 return RETURN_ERR;
10806 }
10807
10808 if (keys == NULL) {
10809 ret = RETURN_ERR;
10810 goto close;
10811 }
10812
10813 keys_it = keys;
10814 while ((read = getline(&line, &len, fd)) != -1) {
10815 //Strip trailing new line if present
10816 if (read > 0 && line[read-1] == '\n') {
10817 line[read-1] = '\0';
10818 }
10819
10820 if(strcmp(line,"keyid=")) {
10821 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10822 if (!(pos = index(line, ' '))) {
10823 ret = RETURN_ERR;
10824 goto close;
10825 }
10826 pos++;
10827 //Here should be 00:00:00:00:00:00
10828 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10829 printf("Not supported MAC: %s\n", pos);
10830 }
10831 if (!(pos = index(pos, ' '))) {
10832 ret = RETURN_ERR;
10833 goto close;
10834 }
10835 pos++;
10836
10837 //The rest is PSK
10838 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10839 keys_it++;
10840
10841 if(--keysNumber <= 0)
10842 break;
10843 }
10844 }
10845
10846close:
10847 free(line);
10848 fclose(fd);
10849 return ret;
10850}
10851/* end of multi-psk support */
10852
10853INT wifi_setNeighborReports(UINT apIndex,
10854 UINT numNeighborReports,
10855 wifi_NeighborReport_t *neighborReports)
10856{
10857 char cmd[256] = { 0 };
10858 char hex_bssid[13] = { 0 };
10859 char bssid[18] = { 0 };
10860 char nr[256] = { 0 };
10861 char ssid[256];
10862 char hex_ssid[256];
10863 INT ret;
10864
10865 /*rmeove all neighbors*/
10866 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10867 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);
10868 system(cmd);
10869
10870 for(unsigned int i = 0; i < numNeighborReports; i++)
10871 {
10872 memset(ssid, 0, sizeof(ssid));
10873 ret = wifi_getSSIDName(apIndex, ssid);
10874 if (ret != RETURN_OK)
10875 return RETURN_ERR;
10876
10877 memset(hex_ssid, 0, sizeof(hex_ssid));
10878 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10879 sprintf(hex_ssid + k,"%02x", ssid[j]);
10880
10881 snprintf(hex_bssid, sizeof(hex_bssid),
10882 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10883 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10884 snprintf(bssid, sizeof(bssid),
10885 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10886 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10887
10888 snprintf(nr, sizeof(nr),
10889 "%s" // bssid
10890 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10891 "%02hhx" // operclass
10892 "%02hhx" // channel
10893 "%02hhx", // phy_mode
10894 hex_bssid,
10895 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10896 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10897 neighborReports[i].opClass,
10898 neighborReports[i].channel,
10899 neighborReports[i].phyTable);
10900
10901 snprintf(cmd, sizeof(cmd),
10902 "hostapd_cli set_neighbor "
10903 "%s " // bssid
10904 "ssid=%s " // ssid
10905 "nr=%s " // nr
10906 "-i %s%d",
10907 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10908
10909 if (WEXITSTATUS(system(cmd)) != 0)
10910 {
10911 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10912 }
10913 }
10914
10915 return RETURN_OK;
10916}
10917
10918INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10919{
10920 return RETURN_OK;
10921}
10922
10923#ifdef _WIFI_HAL_TEST_
10924int main(int argc,char **argv)
10925{
10926 int index;
10927 INT ret=0;
10928 char buf[1024]="";
10929
10930 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10931 if(argc<3)
10932 {
10933 if(argc==2)
10934 {
10935 if(!strcmp(argv[1], "init"))
10936 return wifi_init();
10937 if(!strcmp(argv[1], "reset"))
10938 return wifi_reset();
10939 if(!strcmp(argv[1], "wifi_getHalVersion"))
10940 {
10941 char buffer[64];
10942 if(wifi_getHalVersion(buffer)==RETURN_OK)
10943 printf("Version: %s\n", buffer);
10944 else
10945 printf("Error in wifi_getHalVersion\n");
10946 return RETURN_OK;
10947 }
10948 }
10949 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10950 exit(-1);
10951 }
10952
10953 index = atoi(argv[2]);
10954 if(strstr(argv[1], "wifi_getApName")!=NULL)
10955 {
10956 wifi_getApName(index,buf);
10957 printf("Ap name is %s \n",buf);
10958 return 0;
10959 }
10960 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10961 {
10962 BOOL b = FALSE;
10963 BOOL *output_bool = &b;
10964 wifi_getRadioAutoChannelEnable(index,output_bool);
10965 printf("Channel enabled = %d \n",b);
10966 return 0;
10967 }
10968 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10969 {
10970 wifi_getApWpaEncryptionMode(index,buf);
10971 printf("encryption enabled = %s\n",buf);
10972 return 0;
10973 }
10974 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10975 {
10976 BOOL b = FALSE;
10977 BOOL *output_bool = &b;
10978 wifi_getApSsidAdvertisementEnable(index,output_bool);
10979 printf("advertisment enabled = %d\n",b);
10980 return 0;
10981 }
10982 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10983 {
10984 if(argc <= 3 )
10985 {
10986 printf("Insufficient arguments \n");
10987 exit(-1);
10988 }
10989
10990 char sta[20] = {'\0'};
10991 ULLONG handle= 0;
10992 strcpy(sta,argv[3]);
10993 mac_address_t st;
10994 mac_addr_aton(st,sta);
10995
10996 wifi_associated_dev_tid_stats_t tid_stats;
10997 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10998 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10999 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);
11000 }
11001
11002 if(strstr(argv[1], "getApEnable")!=NULL) {
11003 BOOL enable;
11004 ret=wifi_getApEnable(index, &enable);
11005 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11006 }
11007 else if(strstr(argv[1], "setApEnable")!=NULL) {
11008 BOOL enable = atoi(argv[3]);
11009 ret=wifi_setApEnable(index, enable);
11010 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11011 }
11012 else if(strstr(argv[1], "getApStatus")!=NULL) {
11013 char status[64];
11014 ret=wifi_getApStatus(index, status);
11015 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11016 }
11017 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11018 {
11019 wifi_getSSIDNameStatus(index,buf);
11020 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11021 return 0;
11022 }
11023 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11024 wifi_ssidTrafficStats2_t stats={0};
11025 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11026 printf("%s %d: returns %d\n", argv[1], index, ret);
11027 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11028 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11029 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11030 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11031 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11032 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11033 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11034 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11035 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11036 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11037 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11038 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11039 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11040 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11041 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11042 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11043 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11044 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11045 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11046 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11047 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11048 }
11049 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11050 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11051 UINT array_size=0;
11052 UINT i=0;
11053 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11054 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11055 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11056 printf(" neighbor %d:\n", i);
11057 printf(" ap_SSID =%s\n", pt->ap_SSID);
11058 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11059 printf(" ap_Mode =%s\n", pt->ap_Mode);
11060 printf(" ap_Channel =%d\n", pt->ap_Channel);
11061 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11062 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11063 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11064 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11065 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11066 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11067 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11068 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11069 printf(" ap_Noise =%d\n", pt->ap_Noise);
11070 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11071 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11072 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11073 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11074 }
11075 if(neighbor_ap_array)
11076 free(neighbor_ap_array); //make sure to free the list
11077 }
11078 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11079 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11080 UINT array_size=0;
11081 UINT i=0;
11082 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11083 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11084 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11085 printf(" associated_dev %d:\n", i);
11086 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11087 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11088 printf(" cli_SNR =%d\n", pt->cli_SNR);
11089 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11090 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11091 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11092 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11093 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11094 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11095 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11096 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11097 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11098 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11099 }
11100 if(associated_dev_array)
11101 free(associated_dev_array); //make sure to free the list
11102 }
11103
11104 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11105 {
11106#define MAX_ARRAY_SIZE 64
11107 int i, array_size;
11108 char *p, *ch_str;
11109 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11110
11111 if(argc != 5)
11112 {
11113 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11114 exit(-1);
11115 }
11116 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11117
11118 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11119 {
11120 strtok_r(ch_str, ",", &p);
11121 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11122 }
11123 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11124 if(!array_size)
11125 array_size=1;//Need to print current channel statistics
11126 for(i=0; i<array_size; i++)
11127 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11128 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11129 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11130 input_output_channelStats_array[i].ch_number,\
11131 input_output_channelStats_array[i].ch_noise,\
11132 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11133 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11134 input_output_channelStats_array[i].ch_utilization_busy,\
11135 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11136 input_output_channelStats_array[i].ch_utilization_total);
11137 }
11138
11139 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11140 {
11141 if(argc <= 3 )
11142 {
11143 printf("Insufficient arguments \n");
11144 exit(-1);
11145 }
11146 char mac_addr[20] = {'\0'};
11147 wifi_device_t output_struct;
11148 int dev_index = atoi(argv[3]);
11149
11150 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11151 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11152 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);
11153 }
11154
11155 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11156 {
11157 if (argc <= 3)
11158 {
11159 printf("Insufficient arguments\n");
11160 exit(-1);
11161 }
11162 char args[256];
11163 wifi_NeighborReport_t *neighborReports;
11164
11165 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11166 if (!neighborReports)
11167 {
11168 printf("Failed to allocate memory");
11169 exit(-1);
11170 }
11171
11172 for (int i = 3; i < argc; ++i)
11173 {
11174 char *val;
11175 int j = 0;
11176 memset(args, 0, sizeof(args));
11177 strncpy(args, argv[i], sizeof(args));
11178 val = strtok(args, ";");
11179 while (val != NULL)
11180 {
11181 if (j == 0)
11182 {
11183 mac_addr_aton(neighborReports[i - 3].bssid, val);
11184 } else if (j == 1)
11185 {
11186 neighborReports[i - 3].info = strtol(val, NULL, 16);
11187 } else if (j == 2)
11188 {
11189 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11190 } else if (j == 3)
11191 {
11192 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11193 } else if (j == 4)
11194 {
11195 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11196 } else {
11197 printf("Insufficient arguments]n\n");
11198 exit(-1);
11199 }
11200 val = strtok(NULL, ";");
11201 j++;
11202 }
11203 }
11204
11205 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11206 if (ret != RETURN_OK)
11207 {
11208 printf("wifi_setNeighborReports ret = %d", ret);
11209 exit(-1);
11210 }
11211 }
11212 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11213 {
11214 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11215 printf("%s.\n", buf);
11216 else
11217 printf("Error returned\n");
11218 }
11219 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11220 {
11221 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11222 printf("%s.\n", buf);
11223 else
11224 printf("Error returned\n");
11225 }
11226 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11227 {
11228 if (argc <= 2)
11229 {
11230 printf("Insufficient arguments\n");
11231 exit(-1);
11232 }
11233 char buf[64]= {'\0'};
11234 wifi_getRadioOperatingChannelBandwidth(index,buf);
11235 printf("Current bandwidth is %s \n",buf);
11236 return 0;
11237 }
11238 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11239 {
11240 if (argc <= 5)
11241 {
11242 printf("Insufficient arguments\n");
11243 exit(-1);
11244 }
11245 UINT channel = atoi(argv[3]);
11246 UINT width = atoi(argv[4]);
11247 UINT beacon = atoi(argv[5]);
11248 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11249 printf("Result = %d", ret);
11250 }
11251
11252 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11253 return 0;
11254}
11255
11256#endif
11257
11258#ifdef WIFI_HAL_VERSION_3
11259
developer1e5aa162022-09-13 16:06:24 +080011260INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11261{
11262 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11263 if (bitMap & WIFI_BITRATE_1MBPS)
11264 strcat(BasicRate, "1,");
11265 if (bitMap & WIFI_BITRATE_2MBPS)
11266 strcat(BasicRate, "2,");
11267 if (bitMap & WIFI_BITRATE_5_5MBPS)
11268 strcat(BasicRate, "5.5,");
11269 if (bitMap & WIFI_BITRATE_6MBPS)
11270 strcat(BasicRate, "6,");
11271 if (bitMap & WIFI_BITRATE_9MBPS)
11272 strcat(BasicRate, "9,");
11273 if (bitMap & WIFI_BITRATE_11MBPS)
11274 strcat(BasicRate, "11,");
11275 if (bitMap & WIFI_BITRATE_12MBPS)
11276 strcat(BasicRate, "12,");
11277 if (bitMap & WIFI_BITRATE_18MBPS)
11278 strcat(BasicRate, "18,");
11279 if (bitMap & WIFI_BITRATE_24MBPS)
11280 strcat(BasicRate, "24,");
11281 if (bitMap & WIFI_BITRATE_36MBPS)
11282 strcat(BasicRate, "36,");
11283 if (bitMap & WIFI_BITRATE_48MBPS)
11284 strcat(BasicRate, "48,");
11285 if (bitMap & WIFI_BITRATE_54MBPS)
11286 strcat(BasicRate, "54,");
11287 if (strlen(BasicRate) != 0) // remove last comma
11288 BasicRate[strlen(BasicRate) - 1] = '\0';
11289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11290 return RETURN_OK;
11291}
11292
11293INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11294{
11295 UINT BitMap = 0;
11296 char *rate;
11297
11298 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11299 rate = strtok(BasicRatesList, ",");
11300 while(rate != NULL)
11301 {
11302 if (strcmp(rate, "1") == 0)
11303 BitMap |= WIFI_BITRATE_1MBPS;
11304 else if (strcmp(rate, "2") == 0)
11305 BitMap |= WIFI_BITRATE_2MBPS;
11306 else if (strcmp(rate, "5.5") == 0)
11307 BitMap |= WIFI_BITRATE_5_5MBPS;
11308 else if (strcmp(rate, "6") == 0)
11309 BitMap |= WIFI_BITRATE_6MBPS;
11310 else if (strcmp(rate, "9") == 0)
11311 BitMap |= WIFI_BITRATE_9MBPS;
11312 else if (strcmp(rate, "11") == 0)
11313 BitMap |= WIFI_BITRATE_11MBPS;
11314 else if (strcmp(rate, "12") == 0)
11315 BitMap |= WIFI_BITRATE_12MBPS;
11316 else if (strcmp(rate, "18") == 0)
11317 BitMap |= WIFI_BITRATE_18MBPS;
11318 else if (strcmp(rate, "24") == 0)
11319 BitMap |= WIFI_BITRATE_24MBPS;
11320 else if (strcmp(rate, "36") == 0)
11321 BitMap |= WIFI_BITRATE_36MBPS;
11322 else if (strcmp(rate, "48") == 0)
11323 BitMap |= WIFI_BITRATE_48MBPS;
11324 else if (strcmp(rate, "54") == 0)
11325 BitMap |= WIFI_BITRATE_54MBPS;
11326 rate = strtok(NULL, ",");
11327 }
11328 *basicRateBitMap = BitMap;
11329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11330 return RETURN_OK;
11331}
11332
11333// 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 +080011334INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11335{
developer1e5aa162022-09-13 16:06:24 +080011336 char buf[128] = {0};
11337 char cmd[128] = {0};
11338 char config_file[64] = {0};
11339 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011340 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011341 wifi_radio_operationParam_t current_param;
11342
11343 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11344
11345 multiple_set = TRUE;
11346 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11347 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11348 return RETURN_ERR;
11349 }
11350 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11351 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11352 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11353 return RETURN_ERR;
11354 }
11355 }
developer5884e982022-10-06 10:52:50 +080011356
11357 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11358 bandwidth = 20;
11359 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11360 bandwidth = 40;
11361 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11362 bandwidth = 80;
11363 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11364 bandwidth = 160;
11365 if (operationParam->autoChannelEnabled){
11366 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11367 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11368 return RETURN_ERR;
11369 }
11370 }else{
developer1e5aa162022-09-13 16:06:24 +080011371 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11372 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11373 return RETURN_ERR;
11374 }
11375 }
developer5884e982022-10-06 10:52:50 +080011376
developer1e5aa162022-09-13 16:06:24 +080011377 if (current_param.variant != operationParam->variant) {
11378 // Two different definition bit map, so need to check every bit.
11379 if (operationParam->variant & WIFI_80211_VARIANT_A)
11380 set_mode |= WIFI_MODE_A;
11381 if (operationParam->variant & WIFI_80211_VARIANT_B)
11382 set_mode |= WIFI_MODE_B;
11383 if (operationParam->variant & WIFI_80211_VARIANT_G)
11384 set_mode |= WIFI_MODE_G;
11385 if (operationParam->variant & WIFI_80211_VARIANT_N)
11386 set_mode |= WIFI_MODE_N;
11387 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11388 set_mode |= WIFI_MODE_AC;
11389 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11390 set_mode |= WIFI_MODE_AX;
11391 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11392 memset(buf, 0, sizeof(buf));
11393 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11394 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11395 return RETURN_ERR;
11396 }
11397 }
11398 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11399 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11400 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11401 return RETURN_ERR;
11402 }
11403 }
11404 if (current_param.beaconInterval != operationParam->beaconInterval) {
11405 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11406 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11407 return RETURN_ERR;
11408 }
11409 }
11410 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11411 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11412 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11413 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11414 return RETURN_ERR;
11415 }
11416 }
11417 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11418 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11419 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11420 return RETURN_ERR;
11421 }
11422 }
11423 if (current_param.guardInterval != operationParam->guardInterval) {
11424 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11425 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11426 return RETURN_ERR;
11427 }
11428 }
11429 if (current_param.transmitPower != operationParam->transmitPower) {
11430 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11431 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11432 return RETURN_ERR;
11433 }
11434 }
11435 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11436 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11437 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11438 return RETURN_ERR;
11439 }
11440 }
11441 if (current_param.obssCoex != operationParam->obssCoex) {
11442 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11443 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11444 return RETURN_ERR;
11445 }
11446 }
11447 if (current_param.stbcEnable != operationParam->stbcEnable) {
11448 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11449 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11450 return RETURN_ERR;
11451 }
11452 }
11453 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11454 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11455 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11456 return RETURN_ERR;
11457 }
11458 }
11459
11460 // if enable is true, then restart the radio
11461 wifi_setRadioEnable(index, FALSE);
11462 if (operationParam->enable == TRUE)
11463 wifi_setRadioEnable(index, TRUE);
11464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11465
developer06a01d92022-09-07 16:32:39 +080011466 return RETURN_OK;
11467}
11468
11469INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11470{
developer1e5aa162022-09-13 16:06:24 +080011471 char band[64] = {0};
11472 char buf[256] = {0};
11473 char config_file[64] = {0};
11474 char cmd[128] = {0};
11475 int ret = RETURN_ERR;
11476 int mode = 0;
11477 ULONG channel = 0;
11478 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011479
11480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11481 printf("Entering %s index = %d\n", __func__, (int)index);
11482
developer1e5aa162022-09-13 16:06:24 +080011483 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11484 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11485 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011486 {
developer1e5aa162022-09-13 16:06:24 +080011487 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011488 return RETURN_ERR;
11489 }
11490 operationParam->enable = enabled;
11491
11492 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011493 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011494 {
developer1e5aa162022-09-13 16:06:24 +080011495 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011496 return RETURN_ERR;
11497 }
11498
11499 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011500 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011501 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011502 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011503 else if (!strcmp(band, "6GHz"))
11504 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011505 else
11506 {
developer1e5aa162022-09-13 16:06:24 +080011507 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011508 band);
11509 }
11510
developer1e5aa162022-09-13 16:06:24 +080011511 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11512 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11513 operationParam->channel = 0;
11514 operationParam->autoChannelEnabled = TRUE;
11515 } else {
11516 operationParam->channel = strtol(buf, NULL, 10);
11517 operationParam->autoChannelEnabled = FALSE;
11518 }
11519
developer06a01d92022-09-07 16:32:39 +080011520 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011521 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11522 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11523 return RETURN_ERR;
11524 }
developer06a01d92022-09-07 16:32:39 +080011525 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11526 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11527 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer1e5aa162022-09-13 16:06:24 +080011528 else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11529 else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011530 else
11531 {
developer1e5aa162022-09-13 16:06:24 +080011532 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11533 return false;
developer06a01d92022-09-07 16:32:39 +080011534 }
11535
developer1e5aa162022-09-13 16:06:24 +080011536 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11537 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11538 return RETURN_ERR;
11539 }
11540 // Two different definition bit map, so need to check every bit.
11541 if (mode & WIFI_MODE_A)
11542 operationParam->variant |= WIFI_80211_VARIANT_A;
11543 if (mode & WIFI_MODE_B)
11544 operationParam->variant |= WIFI_80211_VARIANT_B;
11545 if (mode & WIFI_MODE_G)
11546 operationParam->variant |= WIFI_80211_VARIANT_G;
11547 if (mode & WIFI_MODE_N)
11548 operationParam->variant |= WIFI_80211_VARIANT_N;
11549 if (mode & WIFI_MODE_AC)
11550 operationParam->variant |= WIFI_80211_VARIANT_AC;
11551 if (mode & WIFI_MODE_AX)
11552 operationParam->variant |= WIFI_80211_VARIANT_AX;
11553 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11554 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11555 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011556 }
developer1e5aa162022-09-13 16:06:24 +080011557 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11558 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11559 return RETURN_ERR;
11560 }
11561 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11562 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11563 return RETURN_ERR;
11564 }
developer06a01d92022-09-07 16:32:39 +080011565
developer1e5aa162022-09-13 16:06:24 +080011566 memset(buf, 0, sizeof(buf));
11567 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11568 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11569 return RETURN_ERR;
11570 }
11571 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11572
11573 memset(buf, 0, sizeof(buf));
11574 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11575 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11576 return RETURN_ERR;
11577 }
11578 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11579
11580 memset(buf, 0, sizeof(buf));
11581 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11582 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11583
11584 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11585 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11586 return RETURN_ERR;
11587 }
11588 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11589 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11590 return RETURN_ERR;
11591 }
11592
11593 memset(buf, 0, sizeof(buf));
11594 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11595 if (strcmp(buf, "-1") == 0) {
11596 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11597 operationParam->ctsProtection = FALSE;
11598 } else {
11599 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11600 operationParam->ctsProtection = TRUE;
11601 }
11602
11603 memset(buf, 0, sizeof(buf));
11604 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11605 if (strcmp(buf, "0") == 0)
11606 operationParam->obssCoex = FALSE;
11607 else
11608 operationParam->obssCoex = TRUE;
11609
11610 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11611 _syscmd(cmd, buf, sizeof(buf));
11612 if (strlen(buf) != 0)
11613 operationParam->stbcEnable = TRUE;
11614 else
11615 operationParam->stbcEnable = FALSE;
11616
11617 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11618 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11619 return RETURN_ERR;
11620 }
11621
11622 // Below value is hardcoded
11623
11624 operationParam->numSecondaryChannels = 0;
11625 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11626 operationParam->channelSecondary[i] = 0;
11627 }
11628 operationParam->csa_beacon_count = 15;
11629 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011630
11631 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11632 return RETURN_OK;
11633}
11634
11635static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11636{
developerc086fb72022-10-04 10:18:22 +080011637 int max_radio_num = 0;
11638
11639 wifi_getMaxRadioNumber(&max_radio_num);
11640 if (radioIndex >= max_radio_num || radioIndex < 0) {
11641 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11642 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011643 }
11644
developerc086fb72022-10-04 10:18:22 +080011645 return (arrayIndex * max_radio_num) + radioIndex;
11646}
developer06a01d92022-09-07 16:32:39 +080011647
developerc086fb72022-10-04 10:18:22 +080011648wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11649 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11650 return WIFI_BITRATE_1MBPS;
11651 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11652 return WIFI_BITRATE_2MBPS;
11653 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11654 return WIFI_BITRATE_5_5MBPS;
11655 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11656 return WIFI_BITRATE_6MBPS;
11657 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11658 return WIFI_BITRATE_9MBPS;
11659 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11660 return WIFI_BITRATE_11MBPS;
11661 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11662 return WIFI_BITRATE_12MBPS;
11663 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11664 return WIFI_BITRATE_18MBPS;
11665 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11666 return WIFI_BITRATE_24MBPS;
11667 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11668 return WIFI_BITRATE_36MBPS;
11669 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11670 return WIFI_BITRATE_48MBPS;
11671 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11672 return WIFI_BITRATE_54MBPS;
11673 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011674}
11675
11676INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11677{
developerc086fb72022-10-04 10:18:22 +080011678 INT mode = 0;
11679 INT ret = -1;
11680 INT output = 0;
11681 int i = 0;
11682 int vap_index = 0;
11683 BOOL enabled = FALSE;
11684 char buf[256] = {0};
11685 wifi_vap_security_t security;
11686 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011687
11688 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11689 printf("Entering %s index = %d\n", __func__, (int)index);
11690
developer06a01d92022-09-07 16:32:39 +080011691 for (i = 0; i < 5; i++)
11692 {
developerc086fb72022-10-04 10:18:22 +080011693 map->vap_array[i].radio_index = index;
11694
developer06a01d92022-09-07 16:32:39 +080011695 vap_index = array_index_to_vap_index(index, i);
11696 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011697 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011698
developerc086fb72022-10-04 10:18:22 +080011699 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080011700
11701 map->vap_array[i].vap_index = vap_index;
11702
11703 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011704 ret = wifi_getApName(vap_index, buf);
11705 if (ret != RETURN_OK) {
11706 printf("%s: wifi_getApName return error\n", __func__);
11707 return RETURN_ERR;
11708 }
11709 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
11710
11711 memset(buf, 0, sizeof(buf));
11712 ret = wifi_getSSIDNameStatus(vap_index, buf);
11713 if (ret != RETURN_OK) {
11714 printf("%s: wifi_getSSIDNameStatus return error\n", __func__);
11715 return RETURN_ERR;
11716 }
11717 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
developer06a01d92022-09-07 16:32:39 +080011718
11719 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080011720 if (ret != RETURN_OK) {
11721 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011722 return RETURN_ERR;
11723 }
11724 map->vap_array[i].u.bss_info.enabled = enabled;
11725
developerc086fb72022-10-04 10:18:22 +080011726 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
11727 if (ret != RETURN_OK) {
11728 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
11729 return RETURN_ERR;
11730 }
developer06a01d92022-09-07 16:32:39 +080011731 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080011732
11733 ret = wifi_getApIsolationEnable(vap_index, &enabled);
11734 if (ret != RETURN_OK) {
11735 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
11736 return RETURN_ERR;
11737 }
11738 map->vap_array[i].u.bss_info.isolation = enabled;
11739
11740 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
11741 if (ret != RETURN_OK) {
11742 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
11743 return RETURN_ERR;
11744 }
11745 map->vap_array[i].u.bss_info.bssMaxSta = output;
11746
11747 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
11748 if (ret != RETURN_OK) {
11749 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
11750 return RETURN_ERR;
11751 }
11752 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011753
developerc086fb72022-10-04 10:18:22 +080011754 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
11755 if (ret != RETURN_OK) {
11756 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
11757 return RETURN_ERR;
11758 }
11759 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011760
developerc086fb72022-10-04 10:18:22 +080011761 ret = wifi_getApSecurity(vap_index, &security);
11762 if (ret != RETURN_OK) {
11763 printf("%s: wifi_getApSecurity return error\n", __func__);
11764 return RETURN_ERR;
11765 }
11766 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080011767
developerc086fb72022-10-04 10:18:22 +080011768 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
11769 if (ret != RETURN_OK) {
11770 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
11771 return RETURN_ERR;
11772 }
11773 if (mode == 0)
11774 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
11775 else
11776 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
11777 if (mode == 1)
11778 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11779 else if (mode == 2)
11780 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080011781
developerc086fb72022-10-04 10:18:22 +080011782 ret = wifi_getApWmmEnable(vap_index, &enabled);
11783 if (ret != RETURN_OK) {
11784 printf("%s: wifi_getApWmmEnable return error\n", __func__);
11785 return RETURN_ERR;
11786 }
11787 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080011788
developerc086fb72022-10-04 10:18:22 +080011789 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
11790 if (ret != RETURN_OK) {
11791 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011792 return RETURN_ERR;
11793 }
developerc086fb72022-10-04 10:18:22 +080011794 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080011795
11796 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011797 ret = wifi_getApBeaconRate(vap_index, buf);
11798 if (ret != RETURN_OK) {
11799 printf("%s: wifi_getApBeaconRate return error\n", __func__);
11800 return RETURN_ERR;
11801 }
11802 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080011803
developerc086fb72022-10-04 10:18:22 +080011804 memset(buf, 0, sizeof(buf));
11805 ret = wifi_getBaseBSSID(vap_index, buf);
11806 if (ret != RETURN_OK) {
11807 printf("%s: wifi_getBaseBSSID return error\n", __func__);
11808 return RETURN_ERR;
11809 }
11810 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11811 &map->vap_array[i].u.bss_info.bssid[0],
11812 &map->vap_array[i].u.bss_info.bssid[1],
11813 &map->vap_array[i].u.bss_info.bssid[2],
11814 &map->vap_array[i].u.bss_info.bssid[3],
11815 &map->vap_array[i].u.bss_info.bssid[4],
11816 &map->vap_array[i].u.bss_info.bssid[5]);
developer06a01d92022-09-07 16:32:39 +080011817
developerc086fb72022-10-04 10:18:22 +080011818 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080011819 }
11820 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11821 return RETURN_OK;
11822}
11823
11824INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11825{
11826 unsigned int i;
11827 wifi_vap_info_t *vap_info = NULL;
11828 int acl_mode;
11829 char *sec_str = NULL;
11830
11831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11832 printf("Entering %s index = %d\n", __func__, (int)index);
11833 for (i = 0; i < map->num_vaps; i++)
11834 {
11835 vap_info = &map->vap_array[i];
11836 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11837
11838 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11839 else
11840 {
11841 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11842 else acl_mode = 1;
11843 }
11844 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11845 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11846 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11847
11848 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11849 if (sec_str)
11850 {
11851 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11852 }
11853 else
11854 {
11855 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11856 }
11857
11858 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11859 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11860
11861 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11862 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11863
11864 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11865
11866 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11867 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11868 }
11869 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11870 return RETURN_OK;
11871}
11872
11873int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11874{
11875 char *token, *next;
11876 const char s[2] = ",";
11877 int count =0;
11878
11879 /* get the first token */
11880 token = strtok_r(pchannels, s, &next);
11881
11882 /* walk through other tokens */
11883 while( token != NULL && count < MAX_CHANNELS) {
11884 chlistptr->channels_list[count++] = atoi(token);
11885 token = strtok_r(NULL, s, &next);
11886 }
11887
11888 return count;
11889}
11890
11891static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11892{
11893 INT status;
11894 wifi_channels_list_t *chlistp;
11895 CHAR output_string[64];
11896 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011897 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011898
11899 if(rcap == NULL)
11900 {
11901 return RETURN_ERR;
11902 }
11903
11904 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011905 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011906
developer1e5aa162022-09-13 16:06:24 +080011907 if (band == band_2_4)
11908 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11909 else if (band == band_5)
11910 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11911 else if (band == band_6)
11912 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011913
11914 chlistp = &(rcap->channel_list[0]);
11915 memset(pchannels, 0, sizeof(pchannels));
11916
11917 /* possible number of radio channels */
11918 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11919 {
11920 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11921 }
11922 /* Number of channels and list*/
11923 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11924
11925 /* autoChannelSupported */
11926 /* always ON with wifi_getRadioAutoChannelSupported */
11927 rcap->autoChannelSupported = TRUE;
11928
11929 /* DCSSupported */
11930 /* always ON with wifi_getRadioDCSSupported */
11931 rcap->DCSSupported = TRUE;
11932
11933 /* zeroDFSSupported - TBD */
11934 rcap->zeroDFSSupported = FALSE;
11935
11936 /* Supported Country List*/
11937 memset(output_string, 0, sizeof(output_string));
11938 status = wifi_getRadioCountryCode(radioIndex, output_string);
11939 if( status != 0 ) {
11940 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11941 return RETURN_ERR;
11942 } else {
11943 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11944 }
11945 if(!strcmp(output_string,"US")){
11946 rcap->countrySupported[0] = wifi_countrycode_US;
11947 rcap->countrySupported[1] = wifi_countrycode_CA;
11948 } else if (!strcmp(output_string,"CA")) {
11949 rcap->countrySupported[0] = wifi_countrycode_CA;
11950 rcap->countrySupported[1] = wifi_countrycode_US;
11951 } else {
11952 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11953 }
11954
11955 rcap->numcountrySupported = 2;
11956
11957 /* csi */
11958 rcap->csi.maxDevices = 8;
11959 rcap->csi.soudingFrameSupported = TRUE;
11960
11961 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
11962
11963 /* channelWidth - all supported bandwidths */
11964 int i=0;
11965 rcap->channelWidth[i] = 0;
11966 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11967 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11968 WIFI_CHANNELBANDWIDTH_40MHZ);
11969
11970 }
developer1e5aa162022-09-13 16:06:24 +080011971 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080011972 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11973 WIFI_CHANNELBANDWIDTH_40MHZ |
11974 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
11975 }
11976
11977
11978 /* mode - all supported variants */
11979 // rcap->mode[i] = WIFI_80211_VARIANT_H;
11980 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011981 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 +080011982 }
11983 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011984 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
11985 }
11986 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
11987 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011988 }
11989 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
11990 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
11991
11992 /* supportedBitRate - all supported bitrates */
11993 rcap->supportedBitRate[i] = 0;
11994 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11995 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11996 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
11997 }
developer1e5aa162022-09-13 16:06:24 +080011998 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080011999 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12000 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12001 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12002 }
12003
12004
12005 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12006 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12007 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12008 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12009 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12010 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12011 rcap->cipherSupported = 0;
12012 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12013 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12014
12015 return RETURN_OK;
12016}
12017
12018INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12019{
12020 INT status, radioIndex;
12021 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12022 int iter = 0;
12023 unsigned int j;
12024 wifi_interface_name_idex_map_t *iface_info;
12025
12026 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12027
12028 memset(cap, 0, sizeof(wifi_hal_capability_t));
12029
12030 /* version */
12031 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12032 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12033
12034 /* number of radios platform property */
12035 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12036 _syscmd(cmd, output, sizeof(output));
12037 cap->wifi_prop.numRadios = atoi(output);
12038
12039 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12040 {
12041 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12042 if (status != 0) {
12043 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12044 return RETURN_ERR;
12045 }
12046
12047 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12048 {
12049 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
12050 {
12051 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12052 return RETURN_ERR;
12053 }
12054 iface_info = &cap->wifi_prop.interface_map[iter];
12055 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12056 iface_info->rdk_radio_index = radioIndex;
12057 memset(output, 0, sizeof(output));
12058 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12059 {
12060 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12061 }
12062 // TODO: bridge name
12063 // TODO: vlan id
12064 // TODO: primary
12065 iface_info->index = array_index_to_vap_index(radioIndex, j);
12066 memset(output, 0, sizeof(output));
12067 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12068 {
12069 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12070 }
12071 iter++;
12072 }
12073 }
12074
12075 cap->BandSteeringSupported = FALSE;
12076 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12077 return RETURN_OK;
12078}
12079
12080INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12081{
developer587c1b62022-09-27 15:58:59 +080012082 char buf[128] = {0};
12083 char config_file[128] = {0};
12084 char password[64] = {0};
12085 char mfp[32] = {0};
12086 char wpa_mode[32] = {0};
12087 struct params params = {0};
12088
12089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12090
12091 multiple_set = TRUE;
12092 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12093 if (security->mode == wifi_security_mode_none) {
12094 strcpy(wpa_mode, "None");
12095 } else if (security->mode == wifi_security_mode_wpa_personal)
12096 strcpy(wpa_mode, "WPA-Personal");
12097 else if (security->mode == wifi_security_mode_wpa2_personal)
12098 strcpy(wpa_mode, "WPA2-Personal");
12099 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12100 strcpy(wpa_mode, "WPA-WPA2-Personal");
12101 else if (security->mode == wifi_security_mode_wpa_enterprise)
12102 strcpy(wpa_mode, "WPA-Enterprise");
12103 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12104 strcpy(wpa_mode, "WPA2-Enterprise");
12105 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12106 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
12107 else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
12108 strcpy(wpa_mode, "WPA3-Personal");
12109 else if (security->mode == wifi_security_mode_wpa3_enterprise)
12110 strcpy(wpa_mode, "WPA3-Enterprise");
12111
12112 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
12113
12114 strncpy(password, security->u.key.key, 63);
12115 password[63] = '\0';
12116 wifi_setApSecurityKeyPassphrase(ap_index, password);
12117
12118 if (security->mode != wifi_security_mode_none) {
12119 memset(&params, 0, sizeof(params));
12120 params.name = "wpa_pairwise";
12121 if (security->encr == wifi_encryption_tkip)
12122 params.value = "TKIP";
12123 else if (security->encr == wifi_encryption_aes)
12124 params.value = "CCMP";
12125 else if (security->encr == wifi_encryption_aes_tkip)
12126 params.value = "TKIP CCMP";
12127 wifi_hostapdWrite(config_file, &params, 1);
12128 }
12129
12130 if (security->mfp == wifi_mfp_cfg_disabled)
12131 strcpy(mfp, "Disable");
12132 else if (security->mfp == wifi_mfp_cfg_optional)
12133 strcpy(mfp, "Optional");
12134 else if (security->mfp == wifi_mfp_cfg_required)
12135 strcpy(mfp, "Required");
12136 wifi_setApSecurityMFPConfig(ap_index, mfp);
12137
12138 memset(&params, 0, sizeof(params));
12139 params.name = "transition_disable";
12140 if (security->wpa3_transition_disable == TRUE)
12141 params.value = "0x01";
12142 else
12143 params.value = "0x00";
12144 wifi_hostapdWrite(config_file, &params, 1);
12145
12146 memset(&params, 0, sizeof(params));
12147 params.name = "wpa_group_rekey";
12148 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12149 params.value = buf;
12150 wifi_hostapdWrite(config_file, &params, 1);
12151
12152 memset(&params, 0, sizeof(params));
12153 params.name = "wpa_strict_rekey";
12154 params.value = security->strict_rekey?"1":"0";
12155 wifi_hostapdWrite(config_file, &params, 1);
12156
12157 memset(&params, 0, sizeof(params));
12158 params.name = "wpa_pairwise_update_count";
12159 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12160 params.value = buf;
12161 wifi_hostapdWrite(config_file, &params, 1);
12162
12163 memset(&params, 0, sizeof(params));
12164 params.name = "disable_pmksa_caching";
12165 params.value = security->disable_pmksa_caching?"1":"0";
12166 wifi_hostapdWrite(config_file, &params, 1);
12167
12168 wifi_setApEnable(ap_index, FALSE);
12169 wifi_setApEnable(ap_index, TRUE);
12170
12171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12172
developer06a01d92022-09-07 16:32:39 +080012173 return RETURN_OK;
12174}
12175
12176INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12177{
developer587c1b62022-09-27 15:58:59 +080012178 char buf[128] = {0};
12179 char config_file[128] = {0};
12180 int disable = 0;
12181 // struct params params = {0};
12182
12183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12184 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12185 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12186 security->mode = wifi_security_mode_none;
12187 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012188 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012189 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012190 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012191 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012192 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012193 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012194 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012195 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012196 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012197 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012198 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012199 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012200 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012201 security->mode = wifi_security_mode_wpa3_personal;
developer517a9792022-10-05 19:37:42 +080012202 else if (!strcmp(buf, "WPA3-Transition"))
developer587c1b62022-09-27 15:58:59 +080012203 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012204 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012205 security->mode = wifi_security_mode_wpa3_enterprise;
12206 }
12207
12208 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12209 if (security->mode == wifi_security_mode_none)
12210 security->encr = wifi_encryption_none;
12211 else {
12212 if (strcmp(buf, "TKIP") == 0)
12213 security->encr = wifi_encryption_tkip;
12214 else if (strcmp(buf, "CCMP") == 0)
12215 security->encr = wifi_encryption_aes;
12216 else
12217 security->encr = wifi_encryption_aes_tkip;
12218 }
12219
12220 memset(buf, 0, sizeof(buf));
12221 wifi_getApSecurityMFPConfig(ap_index, buf);
12222 if (strcmp(buf, "Disabled") == 0)
12223 security->mfp = wifi_mfp_cfg_disabled;
12224 else if (strcmp(buf, "Optional") == 0)
12225 security->mfp = wifi_mfp_cfg_optional;
12226 else if (strcmp(buf, "Required") == 0)
12227 security->mfp = wifi_mfp_cfg_required;
12228
12229 memset(buf, 0, sizeof(buf));
12230 security->wpa3_transition_disable = FALSE;
12231 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12232 disable = strtol(buf, NULL, 16);
12233 if (disable != 0)
12234 security->wpa3_transition_disable = TRUE;
12235
12236 memset(buf, 0, sizeof(buf));
12237 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12238 if (strlen(buf) == 0)
12239 security->rekey_interval = 86400;
12240 else
12241 security->rekey_interval = strtol(buf, NULL, 10);
12242
12243 memset(buf, 0, sizeof(buf));
12244 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12245 if (strlen(buf) == 0)
12246 security->strict_rekey = 1;
12247 else
12248 security->strict_rekey = strtol(buf, NULL, 10);
12249
12250 memset(buf, 0, sizeof(buf));
12251 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12252 if (strlen(buf) == 0)
12253 security->eapol_key_retries = 4;
12254 else
12255 security->eapol_key_retries = strtol(buf, NULL, 10);
12256
12257 memset(buf, 0, sizeof(buf));
12258 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12259 if (strlen(buf) == 0)
12260 security->disable_pmksa_caching = FALSE;
12261 else
12262 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12263
12264 /* TODO
12265 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12266 */
12267 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12268 security->eap_identity_req_timeout = 0;
12269 security->eap_identity_req_retries = 0;
12270 security->eap_req_timeout = 0;
12271 security->eap_req_retries = 0;
12272 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012273 return RETURN_OK;
12274}
12275
12276#endif /* WIFI_HAL_VERSION_3 */
12277
12278#ifdef WIFI_HAL_VERSION_3_PHASE2
12279INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12280{
developer13df9332022-09-27 16:53:22 +080012281 char cmd[128] = {0};
12282 char buf[128] = {0};
12283 char *mac_addr = NULL;
12284 BOOL status = FALSE;
12285 size_t len = 0;
12286
12287 if(ap_index > MAX_APS)
12288 return RETURN_ERR;
12289
12290 *output_numDevices = 0;
12291 wifi_getApEnable(ap_index, &status);
12292 if (status == FALSE)
12293 return RETURN_OK;
12294
12295 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12296 _syscmd(cmd, buf, sizeof(buf));
12297
12298 mac_addr = strtok(buf, "\n");
12299 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12300 *output_numDevices = i + 1;
12301 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12302 addr_ptr = output_deviceMacAddressArray[i];
12303 mac_addr_aton(addr_ptr, mac_addr);
12304 mac_addr = strtok(NULL, "\n");
12305 }
12306
12307 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012308}
12309#else
12310INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12311{
12312 char cmd[128];
12313 BOOL status = false;
12314
12315 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12316 return RETURN_ERR;
12317
12318 output_buf[0] = '\0';
12319
12320 wifi_getApEnable(ap_index,&status);
12321 if (!status)
12322 return RETURN_OK;
12323
12324 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12325 _syscmd(cmd, output_buf, output_buf_size);
12326
12327 return RETURN_OK;
12328}
12329#endif
developer2f513ab2022-09-13 14:26:06 +080012330
12331INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12332{
12333 char output[16]={'\0'};
12334 char config_file[MAX_BUF_SIZE] = {0};
12335
12336 if (!enable)
12337 return RETURN_ERR;
12338
12339 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12340 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12341
12342 if (strlen(output) == 0)
12343 *enable = FALSE;
12344 else if (strncmp(output, "1", 1) == 0)
12345 *enable = TRUE;
12346 else
12347 *enable = FALSE;
12348
12349 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12350 return RETURN_OK;
12351}
developer2d9c30f2022-09-13 15:06:14 +080012352
12353INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12354{
12355 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12356 return RETURN_ERR;
12357 *output_enable=TRUE;
12358 return RETURN_OK;
12359}
developerfd7d2892022-09-13 16:44:53 +080012360
12361INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12362{
12363 char cmd[128] = {0};
12364 char buf[128] = {0};
12365 char line[128] = {0};
12366 size_t len = 0;
12367 ssize_t read = 0;
12368 FILE *f = NULL;
12369 int index = 0;
12370 int exp = 0;
12371 int mantissa = 0;
12372 int duration = 0;
12373 int radio_index = 0;
12374 int max_radio_num = 0;
12375 uint twt_wake_interval = 0;
12376
12377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12378
12379 wifi_getMaxRadioNumber(&max_radio_num);
12380 radio_index = ap_index % max_radio_num;
12381 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12382 _syscmd(cmd, buf, sizeof(buf));
12383 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12384 if (*numSessionReturned > maxNumberSessions)
12385 *numSessionReturned = maxNumberSessions;
12386 else if (*numSessionReturned < 1) {
12387 *numSessionReturned = 0;
12388 return RETURN_OK;
12389 }
12390
12391 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12392 if ((f = popen(cmd, "r")) == NULL) {
12393 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12394 return RETURN_ERR;
12395 }
12396
12397 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12398 while((read = fgets(line, sizeof(line), f)) != NULL) {
12399 char *tmp = NULL;
12400 strcpy(buf, line);
12401 tmp = strtok(buf, " ");
12402 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12403 tmp = strtok(NULL, " ");
12404 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12405 tmp = strtok(NULL, " ");
12406 if (strstr(tmp, "t")) {
12407 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12408 }
12409 if (strstr(tmp, "a")) {
12410 twtSessions[index].twtParameters.operation.announced = TRUE;
12411 }
12412 tmp = strtok(NULL, " ");
12413 exp = strtol(tmp, NULL, 10);
12414 tmp = strtok(NULL, " ");
12415 mantissa = strtol(tmp, NULL, 10);
12416 tmp = strtok(NULL, " ");
12417 duration = strtol(tmp, NULL, 10);
12418
12419 // only implicit supported
12420 twtSessions[index].twtParameters.operation.implicit = TRUE;
12421 // only individual agreement supported
12422 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12423
12424 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12425 twt_wake_interval = mantissa * (1 << exp);
12426 if (twt_wake_interval/mantissa != (1 << exp)) {
12427 // Overflow handling
12428 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12429 } else {
12430 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12431 }
12432 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12433 index++;
12434 }
12435
12436 pclose(f);
12437 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12438 return RETURN_OK;
12439}