blob: e83397d483ab525881e252ae03a71c88d37ffc24 [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"
developer454b9462022-09-13 15:29:16 +080084
developer06a01d92022-09-07 16:32:39 +080085#define DRIVER_2GHZ "ath9k"
86#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080087#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080088
89/*
90 MAX_APS - Number of all AP available in system
91 2x Home AP
92 2x Backhaul AP
93 2x Guest AP
94 2x Secure Onboard AP
95 2x Service AP
96
97*/
98#define MAX_APS 10
99#define NUMBER_OF_RADIOS 2
100
101#ifndef AP_PREFIX
102#define AP_PREFIX "wifi"
103#endif
104
105#ifndef RADIO_PREFIX
106#define RADIO_PREFIX "wlan"
107#endif
108
109#define MAX_BUF_SIZE 128
110#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800111#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800112
113//Uncomment to enable debug logs
114//#define WIFI_DEBUG
115
116#ifdef WIFI_DEBUG
117#define wifi_dbg_printf printf
118#define WIFI_ENTRY_EXIT_DEBUG printf
119#else
120#define wifi_dbg_printf(format, args...) printf("")
121#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
122#endif
123
124#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
125#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
126#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
127#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
128#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
129#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
130#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
131#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
132#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
133#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
134
135#define HOSTAPD_HT_CAPAB_20 "[SHORT-GI-20]"
136#define HOSTAPD_HT_CAPAB_40 "[SHORT-GI-20][SHORT-GI-40]"
developer3cc0f2e2022-09-15 18:25:39 +0800137#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800138
139#define BW_FNAME "/nvram/bw_file.txt"
140
141#define PS_MAX_TID 16
142
143static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
144 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
145 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
148 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
150 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
152 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
153 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
155 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
156 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
158 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
160};
161
162typedef unsigned long long u64;
163
164/* Enum to define WiFi Bands */
165typedef enum
166{
167 band_invalid = -1,
168 band_2_4 = 0,
169 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800170 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800171} wifi_band;
172
developerdb744382022-09-13 15:34:54 +0800173typedef enum {
174 WIFI_MODE_A = 0x01,
175 WIFI_MODE_B = 0x02,
176 WIFI_MODE_G = 0x04,
177 WIFI_MODE_N = 0x08,
178 WIFI_MODE_AC = 0x10,
179 WIFI_MODE_AX = 0x20,
180} wifi_ieee80211_Mode;
181
developer06a01d92022-09-07 16:32:39 +0800182#ifdef WIFI_HAL_VERSION_3
183
184// Return number of elements in array
185#ifndef ARRAY_SIZE
186#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
187#endif /* ARRAY_SIZE */
188
189#ifndef ARRAY_AND_SIZE
190#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
191#endif /* ARRAY_AND_SIZE */
192
193#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
194
195typedef struct {
196 int32_t value;
197 int32_t param;
198 intptr_t key;
199 intptr_t data;
200} wifi_secur_list;
201
202wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
203wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
204char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800205static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800206
207static wifi_secur_list map_security[] =
208{
209 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
210 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
211 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
218};
219
220wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
221{
222 wifi_secur_list *item;
223 int i;
224
225 for (item = list,i = 0;i < list_sz; item++, i++) {
226 if ((int)(item->key) == key) {
227 return item;
228 }
229 }
230
231 return NULL;
232}
233
234char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
235{
236 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
237
238 if (!item) {
239 return "";
240 }
241
242 return (char *)(item->data);
243}
244
245wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
246{
247 wifi_secur_list *item;
248 int i;
249
250 for (item = list,i = 0;i < list_sz; item++, i++) {
251 if (strcmp((char *)(item->data), str) == 0) {
252 return item;
253 }
254 }
255
256 return NULL;
257}
258#endif /* WIFI_HAL_VERSION_3 */
259
260#ifdef HAL_NETLINK_IMPL
261typedef struct {
262 int id;
263 struct nl_sock* socket;
264 struct nl_cb* cb;
265} Netlink;
266
267static int mac_addr_aton(unsigned char *mac_addr, char *arg)
268{
269 unsigned int mac_addr_int[6]={};
270 sscanf(arg, "%x:%x:%x:%x:%x:%x", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
271 mac_addr[0] = mac_addr_int[0];
272 mac_addr[1] = mac_addr_int[1];
273 mac_addr[2] = mac_addr_int[2];
274 mac_addr[3] = mac_addr_int[3];
275 mac_addr[4] = mac_addr_int[4];
276 mac_addr[5] = mac_addr_int[5];
277 return 0;
278}
279
280static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
281{
282 unsigned int mac_addr_int[6]={};
283 mac_addr_int[0] = arg[0];
284 mac_addr_int[1] = arg[1];
285 mac_addr_int[2] = arg[2];
286 mac_addr_int[3] = arg[3];
287 mac_addr_int[4] = arg[4];
288 mac_addr_int[5] = arg[5];
289 snprintf(mac_addr, 20, "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
290 return;
291}
292
293static int ieee80211_frequency_to_channel(int freq)
294{
295 if (freq == 2484)
296 return 14;
297 else if (freq < 2484)
298 return (freq - 2407) / 5;
299 else if (freq >= 4910 && freq <= 4980)
300 return (freq - 4000) / 5;
301 else if (freq <= 45000)
302 return (freq - 5000) / 5;
303 else if (freq >= 58320 && freq <= 64800)
304 return (freq - 56160) / 2160;
305 else
306 return 0;
307}
308
309static int initSock80211(Netlink* nl) {
310 nl->socket = nl_socket_alloc();
311 if (!nl->socket) {
312 fprintf(stderr, "Failing to allocate the sock\n");
313 return -ENOMEM;
314 }
315
316 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
317
318 if (genl_connect(nl->socket)) {
319 fprintf(stderr, "Failed to connect\n");
320 nl_close(nl->socket);
321 nl_socket_free(nl->socket);
322 return -ENOLINK;
323 }
324
325 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
326 if (nl->id< 0) {
327 fprintf(stderr, "interface not found.\n");
328 nl_close(nl->socket);
329 nl_socket_free(nl->socket);
330 return -ENOENT;
331 }
332
333 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
334 if ((!nl->cb)) {
335 fprintf(stderr, "Failed to allocate netlink callback.\n");
336 nl_close(nl->socket);
337 nl_socket_free(nl->socket);
338 return ENOMEM;
339 }
340
341 return nl->id;
342}
343
344static int nlfree(Netlink *nl)
345{
346 nl_cb_put(nl->cb);
347 nl_close(nl->socket);
348 nl_socket_free(nl->socket);
349 return 0;
350}
351
352static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
353 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
354 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
355 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
356};
357
358static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
359};
360
361static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
362};
363
364typedef struct _wifi_channelStats_loc {
365 INT array_size;
366 INT ch_number;
367 BOOL ch_in_pool;
368 INT ch_noise;
369 BOOL ch_radar_noise;
370 INT ch_max_80211_rssi;
371 INT ch_non_80211_noise;
372 INT ch_utilization;
373 ULLONG ch_utilization_total;
374 ULLONG ch_utilization_busy;
375 ULLONG ch_utilization_busy_tx;
376 ULLONG ch_utilization_busy_rx;
377 ULLONG ch_utilization_busy_self;
378 ULLONG ch_utilization_busy_ext;
379} wifi_channelStats_t_loc;
380
381typedef struct wifi_device_info {
382 INT wifi_devIndex;
383 UCHAR wifi_devMacAddress[6];
384 CHAR wifi_devIPAddress[64];
385 BOOL wifi_devAssociatedDeviceAuthentiationState;
386 INT wifi_devSignalStrength;
387 INT wifi_devTxRate;
388 INT wifi_devRxRate;
389} wifi_device_info_t;
390
391#endif
392
393//For 5g Alias Interfaces
394static BOOL priv_flag = TRUE;
395static BOOL pub_flag = TRUE;
396static BOOL Radio_flag = TRUE;
397//wifi_setApBeaconRate(1, beaconRate);
398
developer1e5aa162022-09-13 16:06:24 +0800399BOOL multiple_set = FALSE;
400
developer06a01d92022-09-07 16:32:39 +0800401struct params
402{
403 char * name;
404 char * value;
405};
406
407static int _syscmd(char *cmd, char *retBuf, int retBufSize)
408{
409 FILE *f;
410 char *ptr = retBuf;
411 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
412
413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
414 if((f = popen(cmd, "r")) == NULL) {
415 fprintf(stderr,"\npopen %s error\n", cmd);
416 return RETURN_ERR;
417 }
418
419 while(!feof(f))
420 {
421 *ptr = 0;
422 if(bufSize>=128) {
423 bufbytes=128;
424 } else {
425 bufbytes=bufSize-1;
426 }
427
428 fgets(ptr,bufbytes,f);
429 readbytes=strlen(ptr);
430
431 if(!readbytes)
432 break;
433
434 bufSize-=readbytes;
435 ptr += readbytes;
436 }
437 cmd_ret = pclose(f);
438 retBuf[retBufSize-1]=0;
439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
440
441 return cmd_ret >> 8;
442}
443
developerc707e972022-09-13 15:38:02 +0800444wifi_band wifi_index_to_band(int apIndex)
445{
446 char cmd[128] = {0};
447 char buf[64] = {0};
448 int freq = 0;
449 wifi_band band = band_invalid;
450
451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
452 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
453 _syscmd(cmd, buf, sizeof(buf));
454 freq = strtol(buf, NULL, 10);
455 if (freq > 2401 && freq < 2495)
456 band = band_2_4;
457 else if (freq > 5160 && freq < 5915)
458 band = band_5;
459 else if (freq > 5955 && freq < 7125)
460 band = band_6;
461
462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
463 return band;
464}
465
developer06a01d92022-09-07 16:32:39 +0800466static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
467{
468 char cmd[MAX_CMD_SIZE]={'\0'};
469 char buf[MAX_BUF_SIZE]={'\0'};
470 int ret = 0;
471
472 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
473 ret = _syscmd(cmd, buf, sizeof(buf));
474 if ((ret != 0) && (strlen(buf) == 0))
475 return -1;
476 snprintf(output, output_size, "%s", buf);
477
478 return 0;
479}
480
481static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
482{
483 char cmd[MAX_CMD_SIZE]={'\0'};
484 char buf[MAX_BUF_SIZE]={'\0'};
485
486 for(int i=0;i<item_count;i++)
487 {
488 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
489 if (strlen(buf) == 0) //Insert
490 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
491 else //Update
492 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
493 if(_syscmd(cmd, buf, sizeof(buf)))
494 return -1;
495 }
496
497 return 0;
498}
499
500static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
501{
developer1e5aa162022-09-13 16:06:24 +0800502 if (multiple_set == TRUE)
503 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800504 char cmd[MAX_CMD_SIZE]="", output[32]="";
505 FILE *fp;
506 int i;
507 //NOTE RELOAD should be done in ApplySSIDSettings
508
509 for(i=0; i<item_count; i++, list++)
510 {
511 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
512 if((fp = popen(cmd, "r"))==NULL)
513 {
514 perror("popen failed");
515 return -1;
516 }
517 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
518 {
519 pclose(fp);
520 perror("fgets failed");
521 return -1;
522 }
523 pclose(fp);
524 }
525 return 0;
526}
527
528static int wifi_reloadAp(int apIndex)
529{
developer1e5aa162022-09-13 16:06:24 +0800530 if (multiple_set == TRUE)
531 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800532 char cmd[MAX_CMD_SIZE]="";
533 char buf[MAX_BUF_SIZE]="";
534
535 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
536 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
537 return RETURN_ERR;
538
539 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
540 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
541 return RETURN_ERR;
542
543 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
544 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
545 return RETURN_ERR;
546
547 return RETURN_OK;
548}
549
550
551//For Getting Current Interface Name from corresponding hostapd configuration
552void GetInterfaceName(char *interface_name, char *conf_file)
553{
554 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
555 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
556 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
557}
558
559INT File_Reading(CHAR *file, char *Value)
560{
561 FILE *fp = NULL;
562 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
563 int count = 0;
564
565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
566 fp = popen(file,"r");
567 if(fp == NULL)
568 return RETURN_ERR;
569
570 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
571 {
572 for(count=0;buf[count]!='\n';count++)
573 copy_buf[count]=buf[count];
574 copy_buf[count]='\0';
575 }
576 strcpy(Value,copy_buf);
577 pclose(fp);
578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
579
580 return RETURN_OK;
581}
582
583void wifi_RestartHostapd_2G()
584{
585 int Public2GApIndex = 4;
586
587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
588 wifi_setApEnable(Public2GApIndex, FALSE);
589 wifi_setApEnable(Public2GApIndex, TRUE);
590 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
591}
592
593void wifi_RestartHostapd_5G()
594{
595 int Public5GApIndex = 5;
596
597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
598 wifi_setApEnable(Public5GApIndex, FALSE);
599 wifi_setApEnable(Public5GApIndex, TRUE);
600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
601}
602
603void wifi_RestartPrivateWifi_2G()
604{
605 int PrivateApIndex = 0;
606
607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
608 wifi_setApEnable(PrivateApIndex, FALSE);
609 wifi_setApEnable(PrivateApIndex, TRUE);
610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
611}
612
613void wifi_RestartPrivateWifi_5G()
614{
615 int Private5GApIndex = 1;
616
617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
618 wifi_setApEnable(Private5GApIndex, FALSE);
619 wifi_setApEnable(Private5GApIndex, TRUE);
620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
621}
622
623static int writeBandWidth(int radioIndex,char *bw_value)
624{
625 char buf[MAX_BUF_SIZE];
626 char cmd[MAX_CMD_SIZE];
627
628 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
629 if(_syscmd(cmd, buf, sizeof(buf)))
630 {
631 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
632 _syscmd(cmd, buf, sizeof(buf));
633 return RETURN_OK;
634 }
635
636 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
637 _syscmd(cmd,buf,sizeof(buf));
638 return RETURN_OK;
639}
640
641static int readBandWidth(int radioIndex,char *bw_value)
642{
643 char buf[MAX_BUF_SIZE];
644 char cmd[MAX_CMD_SIZE];
645 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
646 _syscmd(cmd,buf,sizeof(buf));
647 if(NULL!=strstr(buf,"20MHz"))
648 {
649 strcpy(bw_value,"20MHz");
650 }
651 else if(NULL!=strstr(buf,"40MHz"))
652 {
653 strcpy(bw_value,"40MHz");
654 }
655 else if(NULL!=strstr(buf,"80MHz"))
656 {
657 strcpy(bw_value,"80MHz");
658 }
659 else
660 {
661 return RETURN_ERR;
662 }
663 return RETURN_OK;
664}
665
developer39a5efb2022-09-13 16:09:06 +0800666INT wifi_getMaxRadioNumber(INT *max_radio_num)
667{
668 char cmd[64] = {0};
669 char buf[4] = {0};
670
671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
672
673 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
674 _syscmd(cmd, buf, sizeof(buf));
675 *max_radio_num = strtoul(buf, NULL, 10);
676
677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
678
679 return RETURN_OK;
680}
681
developer5f222492022-09-13 15:21:52 +0800682// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800683INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
684{
developer5f222492022-09-13 15:21:52 +0800685 struct params params={'\0'};
686 char config_file[MAX_BUF_SIZE] = {0};
687 char buf[MAX_BUF_SIZE] = {'\0'};
688
689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
690 if (strlen (beaconRate) < 5)
691 return RETURN_ERR;
692 // Copy the numeric value
693 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
694 buf[strlen(beaconRate) - 4] = '\0';
695
696 params.name = "beacon_rate";
697 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
698 if (strncmp(buf, "5.5", 3) == 0) {
699 snprintf(buf, sizeof(buf), "55");
700 params.value = buf;
701 } else {
702 strcat(buf, "0");
703 params.value = buf;
704 }
705
706 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
707 wifi_hostapdWrite(config_file, &params, 1);
708 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
710
711 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800712}
713
714INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
715{
developer5f222492022-09-13 15:21:52 +0800716 char config_file[MAX_BUF_SIZE] = {'\0'};
717 char temp_output[MAX_BUF_SIZE] = {'\0'};
718 char buf[MAX_BUF_SIZE] = {'\0'};
719 float rate = 0;
720
721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
722 if (NULL == beaconRate)
723 return RETURN_ERR;
724
725 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
726 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
727 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
728 if(strlen(buf) > 0) {
729 rate = atof(buf)/10;
730 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
731 } else {
732 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
733 }
734 strncpy(beaconRate, temp_output, sizeof(temp_output));
735 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
736
737 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800738}
739
740INT wifi_setLED(INT radioIndex, BOOL enable)
741{
742 return 0;
743}
744INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
745{
746 return RETURN_OK;
747}
748/**********************************************************************************
749 *
750 * Wifi Subsystem level function prototypes
751 *
752**********************************************************************************/
753//---------------------------------------------------------------------------------------------------
754//Wifi system api
755//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
756INT wifi_getHalVersion(CHAR *output_string) //RDKB
757{
758 if(!output_string)
759 return RETURN_ERR;
760 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
761
762 return RETURN_OK;
763}
764
765
766/* wifi_factoryReset() function */
767/**
768* @description Clears internal variables to implement a factory reset of the Wi-Fi
769* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
770*
771* @param None
772*
773* @return The status of the operation.
774* @retval RETURN_OK if successful.
775* @retval RETURN_ERR if any error is detected
776*
777* @execution Synchronous
778* @sideeffect None
779*
780* @note This function must not suspend and must not invoke any blocking system
781* calls. It should probably just send a message to a driver event handler task.
782*
783*/
784INT wifi_factoryReset()
785{
786 char cmd[128];
787
788 /*delete running hostapd conf files*/
789 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
790 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
791 system(cmd);
792 system("systemctl restart hostapd.service");
793
794 return RETURN_OK;
795}
796
797/* wifi_factoryResetRadios() function */
798/**
799* @description Restore all radio parameters without touching access point parameters. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
800*
801* @param None
802* @return The status of the operation
803* @retval RETURN_OK if successful
804* @retval RETURN_ERR if any error is detected
805*
806* @execution Synchronous
807*
808* @sideeffect None
809*
810* @note This function must not suspend and must not invoke any blocking system
811* calls. It should probably just send a message to a driver event handler task.
812*
813*/
814INT wifi_factoryResetRadios()
815{
816 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
817 return RETURN_OK;
818
819 return RETURN_ERR;
820}
821
822
823/* wifi_factoryResetRadio() function */
824/**
825* @description Restore selected radio parameters without touching access point parameters
826*
827* @param radioIndex - Index of Wi-Fi Radio channel
828*
829* @return The status of the operation.
830* @retval RETURN_OK if successful.
831* @retval RETURN_ERR if any error is detected
832*
833* @execution Synchronous.
834* @sideeffect None.
835*
836* @note This function must not suspend and must not invoke any blocking system
837* calls. It should probably just send a message to a driver event handler task.
838*
839*/
840INT wifi_factoryResetRadio(int radioIndex) //RDKB
841{
developer5ff7f5f2022-09-13 15:12:16 +0800842 system("systemctl stop hostapd.service");
843
developer06a01d92022-09-07 16:32:39 +0800844 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
845 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800846 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800847 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800848 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800849 else
850 return RETURN_ERR;
851
developer5ff7f5f2022-09-13 15:12:16 +0800852 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800853 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
854 return RETURN_OK;
855}
856
857/* wifi_initRadio() function */
858/**
859* Description: This function call initializes the specified radio.
860* Implementation specifics may dictate the functionality since
861* different hardware implementations may have different initilization requirements.
862* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
863*
864* @return The status of the operation.
865* @retval RETURN_OK if successful.
866* @retval RETURN_ERR if any error is detected
867*
868* @execution Synchronous.
869* @sideeffect None.
870*
871* @note This function must not suspend and must not invoke any blocking system
872* calls. It should probably just send a message to a driver event handler task.
873*
874*/
875INT wifi_initRadio(INT radioIndex)
876{
877 //TODO: Initializes the wifi subsystem (for specified radio)
878 return RETURN_OK;
879}
880void macfilter_init()
881{
882 char count[4]={'\0'};
883 char buf[253]={'\0'};
884 char tmp[19]={'\0'};
885 int dev_count,block,mac_entry=0;
886 char res[4]={'\0'};
887 char acl_file_path[64] = {'\0'};
888 FILE *fp = NULL;
889 int index=0;
890 char iface[10]={'\0'};
891 char config_file[MAX_BUF_SIZE] = {0};
892
893
894 sprintf(acl_file_path,"/tmp/mac_filter.sh");
895
896 fp=fopen(acl_file_path,"w+");
897 sprintf(buf,"#!/bin/sh \n");
898 fprintf(fp,"%s\n",buf);
899
900 system("chmod 0777 /tmp/mac_filter.sh");
901
902 for(index=0;index<=1;index++)
903 {
904 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
905 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
906 sprintf(buf,"syscfg get %dcountfilter",index);
907 _syscmd(buf,count,sizeof(count));
908 mac_entry=atoi(count);
909
910 sprintf(buf,"syscfg get %dblockall",index);
911 _syscmd(buf,res,sizeof(res));
912 block = atoi(res);
913
914 //Allow only those macs mentioned in ACL
915 if(block==1)
916 {
917 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
918 fprintf(fp,"%s\n",buf);
919 for(dev_count=1;dev_count<=mac_entry;dev_count++)
920 {
921 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
922 _syscmd(buf,tmp,sizeof(tmp));
923 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
924 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
925 fprintf(fp,"%s\n",buf);
926 }
927 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
928 fprintf(fp,"%s\n",buf);
929 }
930
931 //Block all the macs mentioned in ACL
932 else if(block==2)
933 {
934 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
935 fprintf(fp,"%s\n",buf);
936
937 for(dev_count=1;dev_count<=mac_entry;dev_count++)
938 {
939 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
940 _syscmd(buf,tmp,sizeof(tmp));
941 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
942 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
943 fprintf(fp,"%s\n",buf);
944 }
945 }
946 }
947 fclose(fp);
948}
949
950// Initializes the wifi subsystem (all radios)
951INT wifi_init() //RDKB
952{
953 char interface[MAX_BUF_SIZE]={'\0'};
954 char bridge_name[MAX_BUF_SIZE]={'\0'};
955 INT len=0;
956
957 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
958 //Not intitializing macfilter for Turris-Omnia Platform for now
959 //macfilter_init();
960
961 system("/usr/sbin/iw reg set US");
962 system("systemctl start hostapd.service");
963 sleep(2);//sleep to wait for hostapd to start
964
965 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
966
967 return RETURN_OK;
968}
969
970/* wifi_reset() function */
971/**
972* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
973* Implementation specifics may dictate what is actualy reset since
974* different hardware implementations may have different requirements.
975* Parameters : None
976*
977* @return The status of the operation.
978* @retval RETURN_OK if successful.
979* @retval RETURN_ERR if any error is detected
980*
981* @execution Synchronous.
982* @sideeffect None.
983*
984* @note This function must not suspend and must not invoke any blocking system
985* calls. It should probably just send a message to a driver event handler task.
986*
987*/
988INT wifi_reset()
989{
990 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +0800991 system("systemctl stop hostapd.service");
992 sleep(2);
993 system("systemctl start hostapd.service");
994 sleep(5);
developer06a01d92022-09-07 16:32:39 +0800995 return RETURN_OK;
996}
997
998/* wifi_down() function */
999/**
1000* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1001* Implementation specifics may dictate some functionality since
1002* different hardware implementations may have different requirements.
1003*
1004* @param None
1005*
1006* @return The status of the operation
1007* @retval RETURN_OK if successful
1008* @retval RETURN_ERR if any error is detected
1009*
1010* @execution Synchronous
1011* @sideeffect None
1012*
1013* @note This function must not suspend and must not invoke any blocking system
1014* calls. It should probably just send a message to a driver event handler task.
1015*
1016*/
1017INT wifi_down()
1018{
1019 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001020 system("systemctl stop hostapd.service");
1021 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001022 return RETURN_OK;
1023}
1024
1025
1026/* wifi_createInitialConfigFiles() function */
1027/**
1028* @description This function creates wifi configuration files. The format
1029* and content of these files are implementation dependent. This function call is
1030* used to trigger this task if necessary. Some implementations may not need this
1031* function. If an implementation does not need to create config files the function call can
1032* do nothing and return RETURN_OK.
1033*
1034* @param None
1035*
1036* @return The status of the operation
1037* @retval RETURN_OK if successful
1038* @retval RETURN_ERR if any error is detected
1039*
1040* @execution Synchronous
1041* @sideeffect None
1042*
1043* @note This function must not suspend and must not invoke any blocking system
1044* calls. It should probably just send a message to a driver event handler task.
1045*
1046*/
1047INT wifi_createInitialConfigFiles()
1048{
1049 //TODO: creates initial implementation dependent configuration files that are later used for variable storage. Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
1050 return RETURN_OK;
1051}
1052
1053// outputs the country code to a max 64 character string
1054INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1055{
developer7543b3b2022-09-13 13:47:17 +08001056 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1057 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001058 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001059
1060 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1061 _syscmd(cmd, buf, sizeof(buf));
1062 if(strlen(buf) > 0)
1063 snprintf(output_string, 64, "%s", buf);
1064 else
1065 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001066
1067 return RETURN_OK;
1068}
1069
1070INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1071{
1072 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001073 char str[MAX_BUF_SIZE]={'\0'};
1074 char cmd[MAX_CMD_SIZE]={'\0'};
1075 struct params params;
1076 char config_file[MAX_BUF_SIZE] = {0};
1077
1078 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1079 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1080 return RETURN_ERR;
1081
1082 params.name = "country_code";
1083 params.value = CountryCode;
1084 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1085 int ret = wifi_hostapdWrite(config_file, &params, 1);
1086 if (ret) {
1087 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1088 ,__func__, ret);
1089 }
1090
1091 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1092 if (ret) {
1093 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1094 ,__func__, ret);
1095 }
1096 wifi_reloadAp(radioIndex);
1097 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1098
developer06a01d92022-09-07 16:32:39 +08001099 return RETURN_OK;
1100}
1101
developera748dcf2022-09-13 15:56:48 +08001102INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1103{
1104 char channel_util_file[64] = {0};
1105 char cmd[128] = {0};
1106 char buf[128] = {0};
1107 char line[128] = {0};
1108 char *param = NULL, *value = NULL;
1109 int read = 0;
1110 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1111 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1112 size_t len = 0;
1113 FILE *f = NULL;
1114
1115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1116
1117 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1118 _syscmd(cmd, buf, sizeof(buf));
1119 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1120
1121 memset(cmd, 0, sizeof(cmd));
1122 memset(buf, 0, sizeof(buf));
1123 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1124 if ((f = popen(cmd, "r")) == NULL) {
1125 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1126 return RETURN_ERR;
1127 }
1128
1129 read = getline(&line, &len, f);
1130 while (read != -1) {
1131 param = strtok(line, ":\t");
1132 value = strtok(NULL, " ");
1133 if(strstr(param, "frequency") != NULL) {
1134 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1135 }
1136 if(strstr(param, "noise") != NULL) {
1137 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1138 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1139 }
1140 if(strstr(param, "channel active time") != NULL) {
1141 ActiveTime = strtol(value, NULL, 10);
1142 }
1143 if(strstr(param, "channel busy time") != NULL) {
1144 BusyTime = strtol(value, NULL, 10);
1145 }
1146 if(strstr(param, "channel transmit time") != NULL) {
1147 TransmitTime = strtol(value, NULL, 10);
1148 }
1149 read = getline(&line, &len, f);
1150 }
1151 pclose(f);
1152
1153 // The file should store the last active, busy and transmit time
1154 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1155 f = fopen(channel_util_file, "r");
1156 if (f != NULL) {
1157 read = getline(&line, &len, f);
1158 preActiveTime = strtol(line, NULL, 10);
1159 read = getline(&line, &len, f);
1160 preBusyTime = strtol(line, NULL, 10);
1161 read = getline(&line, &len, f);
1162 preTransmitTime = strtol(line, NULL, 10);
1163 fclose(f);
1164 }
1165
1166 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1167 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1168
1169 f = fopen(channel_util_file, "w");
1170 if (f != NULL) {
1171 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1172 fclose(f);
1173 }
1174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1175 return RETURN_OK;
1176}
1177
developer06a01d92022-09-07 16:32:39 +08001178/**********************************************************************************
1179 *
1180 * Wifi radio level function prototypes
1181 *
1182**********************************************************************************/
1183
1184//Get the total number of radios in this wifi subsystem
1185INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1186{
1187 if (NULL == output)
1188 return RETURN_ERR;
1189 *output = 2;
1190
1191 return RETURN_OK;
1192}
1193
1194//Get the total number of SSID entries in this wifi subsystem
1195INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1196{
1197 if (NULL == output)
1198 return RETURN_ERR;
1199 *output = MAX_APS;
1200
1201 return RETURN_OK;
1202}
1203
1204//Get the Radio enable config parameter
1205INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1206{
1207 char interface_path[MAX_CMD_SIZE] = {0};
1208 FILE *fp = NULL;
1209
1210 if (NULL == output_bool)
1211 return RETURN_ERR;
1212
1213 *output_bool = FALSE;
1214 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1215 return RETURN_ERR;
1216
1217 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1218 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001219 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001220 {
developercf48e482022-09-13 14:49:50 +08001221 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001222 }
1223 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001224 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1225 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1226 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001227
developercf48e482022-09-13 14:49:50 +08001228 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1229 *output_bool = TRUE;
1230 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001231 return RETURN_OK;
1232}
1233
1234INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1235{
1236 char cmd[MAX_CMD_SIZE] = {0};
1237 char buf[MAX_CMD_SIZE] = {0};
1238 int apIndex, ret;
1239 FILE *fp = NULL;
1240
1241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1242 if(enable==FALSE)
1243 {
1244 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1245 {
1246 //Detaching %s%d from hostapd daemon
1247 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1248 _syscmd(cmd, buf, sizeof(buf));
1249 if(strncmp(buf, "OK", 2))
1250 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1251 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1252 _syscmd(cmd, buf, sizeof(buf));
1253 }
developer456aa3e2022-09-13 14:27:36 +08001254 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001255 _syscmd(cmd, buf, sizeof(buf));
1256 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001257 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001258 }
1259 else
1260 {
developer456aa3e2022-09-13 14:27:36 +08001261 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001262 _syscmd(cmd, buf, sizeof(buf));
1263 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001264 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001265 sleep(1);
1266 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1267 {
1268 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1269 fp = fopen(cmd, "r");
1270 if(!fp)
1271 {
1272 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1273 _syscmd(cmd, buf, sizeof(buf));
1274 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1275 _syscmd(cmd, buf, sizeof(buf));
1276 }
1277 if(fp)
1278 fclose(fp);
1279 }
1280 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1281 {
1282 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1283 ret = _syscmd(cmd, buf, sizeof(buf));
1284 if ( ret == RETURN_ERR)
1285 {
1286 fprintf(stderr, "VAP interface creation failed\n");
1287 continue;
1288 }
1289 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1290 _syscmd(cmd, buf, sizeof(buf));
1291 if(*buf == '1')
1292 {
1293 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1294 radioIndex, apIndex);
1295 _syscmd(cmd, buf, sizeof(buf));
1296 if(strncmp(buf, "OK", 2))
1297 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1298 }
1299 }
1300 }
1301
1302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1303 return RETURN_OK;
1304}
1305
1306//Get the Radio enable status
1307INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1308{
1309 if (NULL == output_bool)
1310 return RETURN_ERR;
1311
1312 return wifi_getRadioEnable(radioIndex, output_bool);
1313}
1314
1315//Get the Radio Interface name from platform, eg "wlan0"
1316INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1317{
1318 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1319 return RETURN_ERR;
1320 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1321
1322 return RETURN_OK;
1323}
1324
1325//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1326//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1327INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1328{
developerbcc556a2022-09-22 20:02:45 +08001329 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1330 // For max bit rate, we should always choose the best MCS
1331 char mode[64] = {0};
1332 char channel_bandwidth_str[16] = {0};
1333 char *tmp = NULL;
1334 UINT mode_map = 0;
1335 UINT num_subcarrier = 0;
1336 UINT code_bits = 0;
1337 float code_rate = 0; // use max code rate
1338 int NSS = 0;
1339 UINT Symbol_duration = 0;
1340 UINT GI_duration = 0;
1341 wifi_band band = band_invalid;
1342 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1343 BOOL enable = FALSE;
1344 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001345
1346 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1347 if (NULL == output_string)
1348 return RETURN_ERR;
1349
developerbcc556a2022-09-22 20:02:45 +08001350 wifi_getRadioEnable(radioIndex, &enable);
1351 if (enable == FALSE) {
1352 snprintf(output_string, 64, "0 Mb/s");
1353 return RETURN_OK;
1354 }
1355
1356 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1357 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1358 return RETURN_ERR;
1359 }
1360
1361 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1362 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1363 return RETURN_ERR;
1364 }
1365
1366 if (gi == wifi_guard_interval_3200)
1367 GI_duration = 32;
1368 else if (gi == wifi_guard_interval_1600)
1369 GI_duration = 16;
1370 else if (gi == wifi_guard_interval_800)
1371 GI_duration = 8;
1372 else // auto, 400
1373 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001374
developerbcc556a2022-09-22 20:02:45 +08001375 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1376 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1377 return RETURN_ERR;
1378 }
1379
1380 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1381 strcpy(channel_bandwidth_str, "160");
1382
1383 if (mode_map & WIFI_MODE_AX) {
1384 if (strstr(channel_bandwidth_str, "160") != NULL)
1385 num_subcarrier = 1960;
1386 else if (strstr(channel_bandwidth_str, "80") != NULL)
1387 num_subcarrier = 980;
1388 else if (strstr(channel_bandwidth_str, "40") != NULL)
1389 num_subcarrier = 468;
1390 else if (strstr(channel_bandwidth_str, "20") != NULL)
1391 num_subcarrier = 234;
1392 code_bits = 10;
1393 code_rate = (float)5/6;
1394 Symbol_duration = 128;
1395 } else if (mode_map & WIFI_MODE_AC) {
1396 if (strstr(channel_bandwidth_str, "160") != NULL)
1397 num_subcarrier = 468;
1398 else if (strstr(channel_bandwidth_str, "80") != NULL)
1399 num_subcarrier = 234;
1400 else if (strstr(channel_bandwidth_str, "40") != NULL)
1401 num_subcarrier = 108;
1402 else if (strstr(channel_bandwidth_str, "20") != NULL)
1403 num_subcarrier = 52;
1404 code_bits = 8;
1405 code_rate = (float)5/6;
1406 Symbol_duration = 32;
1407 } else if (mode_map & WIFI_MODE_N) {
1408 if (strstr(channel_bandwidth_str, "160") != NULL)
1409 num_subcarrier = 468;
1410 else if (strstr(channel_bandwidth_str, "80") != NULL)
1411 num_subcarrier = 234;
1412 else if (strstr(channel_bandwidth_str, "40") != NULL)
1413 num_subcarrier = 108;
1414 else if (strstr(channel_bandwidth_str, "20") != NULL)
1415 num_subcarrier = 52;
1416 code_bits = 6;
1417 code_rate = (float)3/4;
1418 Symbol_duration = 32;
1419 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1420 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1421 snprintf(output_string, 64, "65 Mb/s");
1422 return RETURN_OK;
1423 } else {
1424 snprintf(output_string, 64, "0 Mb/s");
1425 return RETURN_OK;
1426 }
developer06a01d92022-09-07 16:32:39 +08001427
developerbcc556a2022-09-22 20:02:45 +08001428 // Spatial streams
1429 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1430 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1431 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001432 }
developerbcc556a2022-09-22 20:02:45 +08001433
1434 // multiple 10 is to align duration unit (0.1 us)
1435 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1436 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1437
developer06a01d92022-09-07 16:32:39 +08001438 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1439
1440 return RETURN_OK;
1441}
1442#if 0
1443INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1444{
1445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1446 char cmd[64];
1447 char buf[1024];
1448 int apIndex;
1449
1450 if (NULL == output_string)
1451 return RETURN_ERR;
1452
1453 apIndex=(radioIndex==0)?0:1;
1454
1455 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1456 _syscmd(cmd,buf, sizeof(buf));
1457
1458 snprintf(output_string, 64, "%s", buf);
1459 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1460 return RETURN_OK;
1461}
1462#endif
1463
1464
1465//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1466//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1467INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1468{
developer963da0c2022-09-13 15:58:27 +08001469 wifi_band band = band_invalid;
1470
developer06a01d92022-09-07 16:32:39 +08001471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1472 if (NULL == output_string)
1473 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001474
1475 band = wifi_index_to_band(radioIndex);
1476
1477 memset(output_string, 0, 10);
1478 if (band == band_2_4)
1479 strcpy(output_string, "2.4GHz");
1480 else if (band == band_5)
1481 strcpy(output_string, "5GHz");
1482 else if (band == band_6)
1483 strcpy(output_string, "6GHz");
1484 else
1485 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1487
1488 return RETURN_OK;
1489#if 0
1490 char buf[MAX_BUF_SIZE]={'\0'};
1491 char str[MAX_BUF_SIZE]={'\0'};
1492 char cmd[MAX_CMD_SIZE]={'\0'};
1493 char *ch=NULL;
1494 char *ch2=NULL;
1495
1496 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1497 if (NULL == output_string)
1498 return RETURN_ERR;
1499
1500
1501 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1502
1503 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1504 {
1505 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1506 return RETURN_ERR;
1507 }
1508 ch=strchr(buf,'\n');
1509 *ch='\0';
1510 ch=strchr(buf,'=');
1511 if(ch==NULL)
1512 return RETURN_ERR;
1513
1514
1515 ch++;
1516
1517 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1518 strcpy(buf,"0");
1519 if(strlen(ch) == 1)
1520 ch=strcat(buf,ch);
1521
1522
1523 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1524
1525 if(_syscmd(cmd,str,64) == RETURN_ERR)
1526 {
1527 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1528 return RETURN_ERR;
1529 }
1530
1531
1532 ch2=strchr(str,'\n');
1533 //replace \n with \0
1534 *ch2='\0';
1535 ch2=strchr(str,'=');
1536 if(ch2==NULL)
1537 {
1538 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1539 return RETURN_ERR;
1540 }
1541 else
1542 wifi_dbg_printf("%s",ch2+1);
1543
1544
1545 ch2++;
1546
1547
1548 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1549
1550 memset(buf,'\0',sizeof(buf));
1551 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1552 {
1553 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1554 return RETURN_ERR;
1555 }
1556 if (strstr(buf,"2.4") != NULL )
1557 strcpy(output_string,"2.4GHz");
1558 else if(strstr(buf,"5.") != NULL )
1559 strcpy(output_string,"5GHz");
1560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1561
1562 return RETURN_OK;
1563#endif
1564}
1565
1566//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1567//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1568INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1569{
1570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1571 if (NULL == output_string)
1572 return RETURN_ERR;
1573 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1575
1576 return RETURN_OK;
1577#if 0
1578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1579 char buf[MAX_BUF_SIZE]={'\0'};
1580 char str[MAX_BUF_SIZE]={'\0'};
1581 char cmd[MAX_CMD_SIZE]={'\0'};
1582 char *ch=NULL;
1583 char *ch2=NULL;
1584 char ch1[5]="0";
1585
1586 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1587
1588 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1589 {
1590 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1591 return RETURN_ERR;
1592 }
1593
1594 ch=strchr(buf,'\n');
1595 *ch='\0';
1596 ch=strchr(buf,'=');
1597 if(ch==NULL)
1598 return RETURN_ERR;
1599 ch++;
1600
1601 if(strlen(ch)==1)
1602 {
1603 strcat(ch1,ch);
1604
1605 }
1606 else
1607 {
1608 strcpy(ch1,ch);
1609 }
1610
1611
1612
1613 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1614 if(_syscmd(cmd,str,64) == RETURN_ERR)
1615 {
1616 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1617 return RETURN_ERR;
1618 }
1619
1620
1621 ch2=strchr(str,'\n');
1622 //replace \n with \0
1623 *ch2='\0';
1624 ch2=strchr(str,'=');
1625 if(ch2==NULL)
1626 {
1627 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1628 return RETURN_ERR;
1629 }
1630 else
1631 wifi_dbg_printf("%s",ch2+1);
1632 ch2++;
1633
1634
1635 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1636 memset(buf,'\0',sizeof(buf));
1637 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1638 {
1639 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1640 return RETURN_ERR;
1641 }
1642
1643
1644 if(strstr(buf,"2.4")!=NULL)
1645 {
1646 strcpy(output_string,"2.4GHz");
1647 }
1648 if(strstr(buf,"5.")!=NULL)
1649 {
1650 strcpy(output_string,"5GHz");
1651 }
1652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1653 return RETURN_OK;
1654#endif
1655}
1656
1657//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1658//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1659INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1660{
developer963da0c2022-09-13 15:58:27 +08001661 char cmd[128]={0};
1662 char buf[128]={0};
1663 char temp_output[128] = {0};
1664 wifi_band band;
1665
1666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001667 if (NULL == output_string)
1668 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001669
1670 band = wifi_index_to_band(radioIndex);
1671 if (band == band_2_4) {
1672 strcat(temp_output, "b,g,");
1673 } else if (band == band_5) {
1674 strcat(temp_output, "a,");
1675 }
1676
1677 // ht capabilities
1678 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", radioIndex);
1679 _syscmd(cmd, buf, sizeof(buf));
1680 if (strncmp(buf, "0x00", 4) != 0) {
1681 strcat(temp_output, "n,");
1682 }
developer06a01d92022-09-07 16:32:39 +08001683
developer963da0c2022-09-13 15:58:27 +08001684 // vht capabilities
1685 if (band == band_5) {
1686 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1687 _syscmd(cmd, buf, sizeof(buf));
1688 if (strncmp(buf, "0x00000000", 10) != 0) {
1689 strcat(temp_output, "ac,");
1690 }
1691 }
1692
1693 // he capabilities
1694 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", radioIndex);
1695 _syscmd(cmd, buf, sizeof(buf));
1696 if (strncmp (buf, "0x0000", 6) != 0) {
1697 strcat(temp_output, "ax,");
1698 }
1699
1700 // Remove the last comma
1701 if (strlen(temp_output) != 0)
1702 temp_output[strlen(temp_output)-1] = '\0';
1703 strncpy(output_string, temp_output, strlen(temp_output));
1704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001705 return RETURN_OK;
1706}
1707
1708//Get the radio operating mode, and pure mode flag. eg: "ac"
1709//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1710INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1711{
1712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1713 if (NULL == output_string)
1714 return RETURN_ERR;
1715
1716 if (radioIndex == 0) {
1717 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1718 *gOnly = FALSE;
1719 *nOnly = TRUE;
1720 *acOnly = FALSE;
1721 } else {
1722 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1723 *gOnly = FALSE;
1724 *nOnly = FALSE;
1725 *acOnly = FALSE;
1726 }
1727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1728
1729 return RETURN_OK;
1730#if 0
1731 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1732 char buf[64] = {0};
1733 char config_file[MAX_BUF_SIZE] = {0};
1734
1735 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1736 return RETURN_ERR;
1737
1738 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1739 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1740
1741 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1742 if (strlen(buf) == 0)
1743 {
1744 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1745 return RETURN_ERR;
1746 }
1747 if(strcmp(buf,"g")==0)
1748 {
1749 wifi_dbg_printf("\nG\n");
1750 *gOnly=TRUE;
1751 *nOnly=FALSE;
1752 *acOnly=FALSE;
1753 }
1754 else if(strcmp(buf,"n")==0)
1755 {
1756 wifi_dbg_printf("\nN\n");
1757 *gOnly=FALSE;
1758 *nOnly=TRUE;
1759 *acOnly=FALSE;
1760 }
1761 else if(strcmp(buf,"ac")==0)
1762 {
1763 wifi_dbg_printf("\nac\n");
1764 *gOnly=FALSE;
1765 *nOnly=FALSE;
1766 *acOnly=TRUE;
1767 }
1768 /* hostapd-5G.conf has "a" as hw_mode */
1769 else if(strcmp(buf,"a")==0)
1770 {
1771 wifi_dbg_printf("\na\n");
1772 *gOnly=FALSE;
1773 *nOnly=FALSE;
1774 *acOnly=FALSE;
1775 }
1776 else
1777 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1778
1779 //for a,n mode
1780 if(radioIndex == 1)
1781 {
1782 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1783 if(strcmp(buf,"1")==0)
1784 {
1785 strncpy(output_string, "n", 1);
1786 *nOnly=FALSE;
1787 }
1788 }
1789
1790 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1792 return RETURN_OK;
1793#endif
1794}
1795
developerdb744382022-09-13 15:34:54 +08001796INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1797{
1798 char cmd[128] = {0};
1799 char buf[64] = {0};
1800 char config_file[64] = {0};
1801 wifi_band band;
1802
1803 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1804 if(NULL == output_string || NULL == pureMode)
1805 return RETURN_ERR;
1806
1807 // grep all of the ieee80211 protocol config set to 1
1808 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1809 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1810 _syscmd(cmd, buf, sizeof(buf));
1811
1812 band = wifi_index_to_band(radioIndex);
1813 // puremode is a bit map
1814 *pureMode = 0;
1815 if (band == band_2_4) {
1816 strcat(output_string, "b,g");
1817 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1818 if (strstr(buf, "n") != NULL) {
1819 strcat(output_string, ",n");
1820 *pureMode |= WIFI_MODE_N;
1821 }
1822 if (strstr(buf, "ax") != NULL) {
1823 strcat(output_string, ",ax");
1824 *pureMode |= WIFI_MODE_AX;
1825 }
1826 } else if (band == band_5) {
1827 strcat(output_string, "a");
1828 *pureMode |= WIFI_MODE_A;
1829 if (strstr(buf, "n") != NULL) {
1830 strcat(output_string, ",n");
1831 *pureMode |= WIFI_MODE_N;
1832 }
1833 if (strstr(buf, "ac") != NULL) {
1834 strcat(output_string, ",ac");
1835 *pureMode |= WIFI_MODE_AC;
1836 }
1837 if (strstr(buf, "ax") != NULL) {
1838 strcat(output_string, ",ax");
1839 *pureMode |= WIFI_MODE_AX;
1840 }
1841 } else if (band == band_6) {
1842 if (strstr(buf, "ax") != NULL) {
1843 strcat(output_string, "ax");
1844 *pureMode |= WIFI_MODE_AX;
1845 }
1846 }
1847
1848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1849 return RETURN_OK;
1850}
1851
1852// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001853INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1854{
1855 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1856 if (strcmp (channelMode,"11A") == 0)
1857 {
1858 writeBandWidth(radioIndex,"20MHz");
1859 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1860 printf("\nChannel Mode is 802.11a (5GHz)\n");
1861 }
1862 else if (strcmp (channelMode,"11NAHT20") == 0)
1863 {
1864 writeBandWidth(radioIndex,"20MHz");
1865 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1866 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1867 }
1868 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1869 {
1870 writeBandWidth(radioIndex,"40MHz");
1871 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1872 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1873 }
1874 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1875 {
1876 writeBandWidth(radioIndex,"40MHz");
1877 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1878 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1879 }
1880 else if (strcmp (channelMode,"11ACVHT20") == 0)
1881 {
1882 writeBandWidth(radioIndex,"20MHz");
1883 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1884 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1885 }
1886 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1887 {
1888 writeBandWidth(radioIndex,"40MHz");
1889 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1890 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1891 }
1892 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1893 {
1894 writeBandWidth(radioIndex,"40MHz");
1895 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1896 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1897 }
1898 else if (strcmp (channelMode,"11ACVHT80") == 0)
1899 {
1900 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1901 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1902 }
1903 else if (strcmp (channelMode,"11ACVHT160") == 0)
1904 {
1905 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1906 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1907 }
1908 else if (strcmp (channelMode,"11B") == 0)
1909 {
1910 writeBandWidth(radioIndex,"20MHz");
1911 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1912 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1913 }
1914 else if (strcmp (channelMode,"11G") == 0)
1915 {
1916 writeBandWidth(radioIndex,"20MHz");
1917 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1918 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1919 }
1920 else if (strcmp (channelMode,"11NGHT20") == 0)
1921 {
1922 writeBandWidth(radioIndex,"20MHz");
1923 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1924 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1925 }
1926 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1927 {
1928 writeBandWidth(radioIndex,"40MHz");
1929 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1930 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1931 }
1932 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1933 {
1934 writeBandWidth(radioIndex,"40MHz");
1935 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1936 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1937 }
1938 else
1939 {
1940 return RETURN_ERR;
1941 }
1942 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1943
1944 return RETURN_OK;
1945}
1946
developerdb744382022-09-13 15:34:54 +08001947// Set the radio operating mode, and pure mode flag.
1948INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1949{
1950 int num_hostapd_support_mode = 3; // n, ac, ax
1951 struct params list[num_hostapd_support_mode];
1952 char config_file[64] = {0};
1953 char bandwidth[16] = {0};
1954 int mode_check_bit = 1 << 3; // n mode
1955 wifi_ieee80211_Mode mode = (wifi_ieee80211_Mode)pureMode;
1956
1957 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1958 // Set radio mode
1959 list[0].name = "ieee80211n";
1960 list[1].name = "ieee80211ac";
1961 list[2].name = "ieee80211ax";
1962 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1963
1964 // check the bit map from n to ax, and set hostapd config
1965 if (mode & WIFI_MODE_N)
1966 list[0].value = "1";
1967 else
1968 list[0].value = "0";
1969 if (mode & WIFI_MODE_AC)
1970 list[1].value = "1";
1971 else
1972 list[1].value = "0";
1973 if (mode & WIFI_MODE_AX)
1974 list[2].value = "1";
1975 else
1976 list[2].value = "0";
1977 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1978
1979 if (channelMode == NULL || strlen(channelMode) == 0)
1980 return RETURN_OK;
1981 // Set bandwidth
1982 if (strstr(channelMode, "40") != NULL)
1983 strcpy(bandwidth, "40MHz");
1984 else if (strstr(channelMode, "80") != NULL)
1985 strcpy(bandwidth, "80MHz");
1986 else if (strstr(channelMode, "160") != NULL)
1987 strcpy(bandwidth, "160MHz");
1988 else // 11A, 11B, 11G....
1989 strcpy(bandwidth, "20MHz");
1990
1991 writeBandWidth(radioIndex, bandwidth);
1992 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
1993
1994 wifi_reloadAp(radioIndex);
1995 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1996
1997 return RETURN_OK;
1998}
1999
developer06a01d92022-09-07 16:32:39 +08002000//Get the list of supported channel. eg: "1-11"
2001//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2002INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2003{
developer6318ed52022-09-13 15:17:58 +08002004 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002005 if (NULL == output_string)
2006 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002007 char cmd[256] = {0};
2008 char buf[128] = {0};
2009 BOOL dfs_enable = false;
2010 // Parse possible channel number and separate them with commas.
2011 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2012 if (dfs_enable)
2013 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
2014 else
2015 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
2016
2017 _syscmd(cmd,buf,sizeof(buf));
2018 strncpy(output_string, buf, sizeof(buf));
2019
2020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2021 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002022#if 0
2023 char IFName[50] ={0};
2024 char buf[MAX_BUF_SIZE] = {0};
2025 char cmd[MAX_CMD_SIZE] = {0};
2026 int count = 0;
2027 if (NULL == output_string)
2028 return RETURN_ERR;
2029
2030 //snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2031 if(radioIndex == 0)
2032 {
2033 GetInterfaceName(IFName,"/nvram/hostapd0.conf");
2034 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 2'\\.' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | sed 's/^0//g' | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2035 }
2036 else if(radioIndex == 1)
2037 {
2038 GetInterfaceName(IFName,"/nvram/hostapd1.conf");
2039 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep '5\\.[1-9]' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2040 }
2041 _syscmd(cmd, buf, sizeof(buf));
2042 if(strlen(buf) > 0)
2043 strcpy(output_string,buf);
2044 else
2045 strcpy(output_string,"0");
2046#endif
2047 return RETURN_OK;
2048}
2049
2050//Get the list for used channel. eg: "1,6,9,11"
2051//The output_string is a max length 256 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2052INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2053{
2054 if (NULL == output_string)
2055 return RETURN_ERR;
2056 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
2057#if 0
2058 char IFName[50] ={0};
2059 char buf[MAX_BUF_SIZE] = {0};
2060 char cmd[MAX_CMD_SIZE] = {0};
2061 if (NULL == output_string)
2062 return RETURN_ERR;
2063
2064 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2065 if(radioIndex == 0)
2066 {
2067 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
2068 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 2'\\.' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | sed 's/^0//g' | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2069 }
2070 else if(radioIndex == 1)
2071 {
2072 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
2073 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 5'\\.[1-9]' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 |tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2074 }
2075 _syscmd(cmd,buf, sizeof(buf));
2076 if(strlen(buf) > 0)
2077 strcpy(output_string,buf);
2078 else
2079 strcpy(output_string,"0");
2080#endif
2081 return RETURN_OK;
2082}
2083
2084//Get the running channel number
2085INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2086{
developerda1ed692022-09-13 13:59:20 +08002087#ifdef MTK_IMPL
2088 if(!wifi_getApChannel(radioIndex, output_ulong))
2089 return RETURN_OK;
2090 else
2091 return RETURN_ERR;
2092#else
developer06a01d92022-09-07 16:32:39 +08002093 char cmd[1024] = {0}, buf[5] = {0};
2094
2095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2096 if (NULL == output_ulong)
2097 return RETURN_ERR;
2098
2099 snprintf(cmd, sizeof(cmd),
2100 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2101 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2102 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2103 _syscmd(cmd, buf, sizeof(buf));
2104
2105 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2106 if (*output_ulong <= 0) {
2107 *output_ulong = 0;
2108 return RETURN_ERR;
2109 }
2110
2111 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2112 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002113#endif
developer06a01d92022-09-07 16:32:39 +08002114}
2115
2116
2117INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2118{
2119 char cmd[1024] = {0}, buf[5] = {0};
2120 char interface_name[50] = {0};
2121
2122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2123 if (NULL == output_ulong)
2124 return RETURN_ERR;
2125
2126 wifi_getApName(apIndex,interface_name);
2127 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2128 _syscmd(cmd,buf,sizeof(buf));
2129 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2130 if (*output_ulong == 0) {
2131 return RETURN_ERR;
2132 }
2133
2134 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2135 return RETURN_OK;
2136}
2137
2138//Storing the previous channel value
2139INT wifi_storeprevchanval(INT radioIndex)
2140{
2141 char buf[256] = {0};
2142 char output[4]={'\0'};
2143 char config_file[MAX_BUF_SIZE] = {0};
2144 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2145 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2146 if(radioIndex == 0)
2147 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2148 else if(radioIndex == 1)
2149 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2150 system(buf);
2151 Radio_flag = FALSE;
2152 return RETURN_OK;
2153}
2154
2155//Set the running channel number
2156INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2157{
2158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2159 struct params params={'\0'};
2160 char str_channel[4]={'\0'};
2161 struct params list;
2162 char config_file[MAX_BUF_SIZE] = {0};
2163
2164 list.name = "channel";
2165
2166 if(Radio_flag == TRUE)
2167 wifi_storeprevchanval(radioIndex); //for autochannel
2168
2169 if(radioIndex == 0)
2170 {
2171 switch(channel)
2172 {
2173 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
2174 sprintf(str_channel,"%ld", channel);
2175 list.value = str_channel;
2176 break;
2177 default:
2178 return RETURN_ERR;
2179 }
2180 }
2181 else if(radioIndex == 1)
2182 {
2183 switch(channel)
2184 {
2185 case 36: case 40: case 44: case 48: case 52: case 56: case 60: case 64: case 144: case 149: case 153: case 157: case 161: case 165: case 169:
2186 sprintf(str_channel,"%ld", channel);
2187 list.value = str_channel;
2188 break;
2189 default:
2190 return RETURN_ERR;
2191 }
2192 }
2193
2194 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS;i++)
2195 {
2196 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2197 wifi_hostapdWrite(config_file,&list,1);
2198 }
2199
2200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2201 return RETURN_OK;
2202 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2203 }
2204
2205INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2206{
2207 struct params list;
2208 char str_idx[16];
2209 char config_file[MAX_BUF_SIZE];
2210
2211 list.name = "vht_oper_centr_freq_seg0_idx";
2212 snprintf(str_idx, sizeof(str_idx), "%d", channel);
2213 list.value = str_idx;
2214
2215 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2216 {
2217 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2218 wifi_hostapdWrite(config_file, &list, 1);
2219 }
2220
2221 return RETURN_OK;
2222}
2223
2224//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2225//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2226INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2227{
2228 //Set to wifi config only. Wait for wifi reset to apply.
2229 char buf[256] = {0};
2230 char str_channel[256] = {0};
2231 int count = 0;
2232 ULONG Value = 0;
2233 FILE *fp = NULL;
2234 if(enable == TRUE)
2235 {
2236 if(radioIndex == 0)
2237 {
2238 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
2239 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
2240 }
2241 else if(radioIndex == 1)
2242 {
2243 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
2244 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
2245 }
2246 if(fp == NULL) //first time boot-up
2247 {
2248 if(radioIndex == 0)
2249 Value = 6;
2250 else if(radioIndex == 1)
2251 Value = 36;
2252 }
2253 else
2254 {
2255 if(fgets(buf,sizeof(buf),fp) != NULL)
2256 {
2257 for(count = 0;buf[count]!='\n';count++)
2258 str_channel[count] = buf[count];
2259 str_channel[count] = '\0';
2260 Value = atol(str_channel);
2261 printf("%sValue is %ld \n",__FUNCTION__,Value);
2262 pclose(fp);
2263 }
2264 }
2265 Radio_flag = FALSE;//for storing previous channel value
2266 wifi_setRadioChannel(radioIndex,Value);
2267 return RETURN_OK;
2268 }
2269 return RETURN_ERR;
2270}
2271
2272INT wifi_getRadioDCSSupported(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_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2281{
2282 if (NULL == output_bool)
2283 return RETURN_ERR;
2284 *output_bool=FALSE;
2285 return RETURN_OK;
2286}
2287
2288INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2289{
2290 //Set to wifi config only. Wait for wifi reset to apply.
2291 return RETURN_OK;
2292}
2293
2294INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2295{
2296 return RETURN_OK;
2297}
2298
2299INT wifi_factoryResetAP(int apIndex)
2300{
2301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2302 //factory reset is not done for now on Turris
2303 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2304 return RETURN_OK;
2305}
2306
2307//To set Band Steering AP group
2308//To-do
2309INT wifi_setBandSteeringApGroup(char *ApGroup)
2310{
2311 return RETURN_OK;
2312}
2313
developer1e5aa162022-09-13 16:06:24 +08002314INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2315{
2316 char config_file[128] = {'\0'};
2317 char buf[128] = {'\0'};
2318
2319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2320 if (dtimInterval == NULL)
2321 return RETURN_ERR;
2322
2323 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2324 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2325
2326 if (strlen(buf) == 0) {
2327 *dtimInterval = 2;
2328 } else {
2329 *dtimInterval = strtoul(buf, NULL, 10);
2330 }
2331
2332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2333 return RETURN_OK;
2334}
2335
developer06a01d92022-09-07 16:32:39 +08002336INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2337{
developer5f222492022-09-13 15:21:52 +08002338 struct params params={0};
2339 char config_file[MAX_BUF_SIZE] = {'\0'};
2340 char buf[MAX_BUF_SIZE] = {'\0'};
2341
2342 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2343 if (dtimInterval < 1 || dtimInterval > 255) {
2344 return RETURN_ERR;
2345 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2346 }
2347
2348 params.name = "dtim_period";
2349 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2350 params.value = buf;
2351
2352 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2353 wifi_hostapdWrite(config_file, &params, 1);
2354 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2355
2356 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2357 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002358}
2359
2360//Check if the driver support the Dfs
2361INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2362{
2363 if (NULL == output_bool)
2364 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002365 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002366 return RETURN_OK;
2367}
2368
2369//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.
2370//The value of this parameter is a comma seperated list of channel number
2371INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2372{
2373 if (NULL == output_pool)
2374 return RETURN_ERR;
2375 if (radioIndex==1)
2376 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2377 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2378
2379 return RETURN_OK;
2380}
2381
2382INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2383{
2384 //Set to wifi config. And apply instantly.
2385 return RETURN_OK;
2386}
2387
2388INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2389{
2390 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2391 return RETURN_ERR;
2392 *output_interval_seconds=1800;
2393 *output_dwell_milliseconds=40;
2394
2395 return RETURN_OK;
2396}
2397
2398INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2399{
2400 //Set to wifi config. And apply instantly.
2401 return RETURN_OK;
2402}
2403
2404//Get the Dfs enable status
2405INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2406{
developer9964b5b2022-09-13 15:59:34 +08002407 char buf[16] = {0};
2408 FILE *f = NULL;
2409 wifi_band band;
2410
2411 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2412
2413 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002414 if (NULL == output_bool)
2415 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002416
2417 band = wifi_index_to_band(radioIndex);
2418 if (band != band_5)
2419 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002420
developer9964b5b2022-09-13 15:59:34 +08002421 f = fopen(DFS_ENABLE_FILE, "r");
2422 if (f != NULL) {
2423 fgets(buf, 2, f);
2424 if (strncmp(buf, "0", 0) == 0)
2425 *output_bool = FALSE;
2426 fclose(f);
2427 }
2428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002429 return RETURN_OK;
2430}
2431
2432//Set the Dfs enable status
2433INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2434{
developer9964b5b2022-09-13 15:59:34 +08002435 char buf[128] = {0};
2436 char config_file[128] = {0};
2437 FILE *f = NULL;
2438 struct params params={0};
2439 wifi_band band;
2440
2441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2442
2443 band = wifi_index_to_band(radioIndex);
2444 if (band != band_5)
2445 return RETURN_OK;
2446
2447 f = fopen(DFS_ENABLE_FILE, "w");
2448 if (f == NULL)
2449 return RETURN_ERR;
2450 fprintf(f, "%d", enable);
2451 fclose(f);
2452
2453 params.name = "acs_exclude_dfs";
2454 sprintf(buf, "%d", enable?"1":"0");
2455 params.value = buf;
2456 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2457 wifi_hostapdWrite(config_file, &params, 1);
2458 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2459
2460 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2461
2462 wifi_reloadAp(radioIndex);
2463
2464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002465}
2466
2467//Check if the driver support the AutoChannelRefreshPeriod
2468INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2469{
2470 if (NULL == output_bool)
2471 return RETURN_ERR;
2472 *output_bool=FALSE; //not support
2473
2474 return RETURN_OK;
2475}
2476
2477//Get the ACS refresh period in seconds
2478INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2479{
2480 if (NULL == output_ulong)
2481 return RETURN_ERR;
2482 *output_ulong=300;
2483
2484 return RETURN_OK;
2485}
2486
2487//Set the ACS refresh period in seconds
2488INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2489{
2490 return RETURN_ERR;
2491}
2492
2493//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2494//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.
2495INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2496{
developer70490032022-09-13 15:45:20 +08002497 char cmd[128] = {0}, buf[64] = {0};
2498 char interface_name[64] = {0};
2499 int ret = 0, len=0;
2500 BOOL radio_enable = FALSE;
2501
2502 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2503
developer06a01d92022-09-07 16:32:39 +08002504 if (NULL == output_string)
2505 return RETURN_ERR;
2506
developer70490032022-09-13 15:45:20 +08002507 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2508 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002509
developer70490032022-09-13 15:45:20 +08002510 if (radio_enable != TRUE)
2511 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002512
developer70490032022-09-13 15:45:20 +08002513 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002514 ret = _syscmd(cmd, buf, sizeof(buf));
2515 len = strlen(buf);
2516 if((ret != 0) || (len == 0))
2517 {
2518 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2519 return RETURN_ERR;
2520 }
2521
2522 buf[len-1] = '\0';
2523 snprintf(output_string, 64, "%sMHz", buf);
2524 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2525
2526#if 0
2527 //TODO: revisit below implementation
2528 char output_buf[8]={0};
2529 char bw_value[10];
2530 char config_file[MAX_BUF_SIZE] = {0};
2531
2532 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2533 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2534 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2535 readBandWidth(radioIndex,bw_value);
2536
2537 if(strstr (output_buf,"0") != NULL )
2538 {
2539 strcpy(output_string,bw_value);
2540 }
2541 else if (strstr (output_buf,"1") != NULL)
2542 {
2543 strcpy(output_string,"80MHz");
2544 }
2545 else if (strstr (output_buf,"2") != NULL)
2546 {
2547 strcpy(output_string,"160MHz");
2548 }
2549 else if (strstr (output_buf,"3") != NULL)
2550 {
2551 strcpy(output_string,"80+80");
2552 }
2553 else
2554 {
2555 strcpy(output_string,"Auto");
2556 }
2557 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2558#endif
2559
2560 return RETURN_OK;
2561}
2562
2563//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002564INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002565{
developerf7a466e2022-09-29 11:55:56 +08002566 char config_file[128];
2567 char set_value[16];
2568 struct params params[2];
2569 int max_radio_num = 0;
2570
developer06a01d92022-09-07 16:32:39 +08002571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002572
developerf7a466e2022-09-29 11:55:56 +08002573 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002574 return RETURN_ERR;
2575
developerf7a466e2022-09-29 11:55:56 +08002576 if(strstr(bandwidth,"80+80") != NULL)
2577 strcpy(set_value, "3");
2578 else if(strstr(bandwidth,"160") != NULL)
2579 strcpy(set_value, "2");
2580 else if(strstr(bandwidth,"80") != NULL)
2581 strcpy(set_value, "1");
2582 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2583 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002584 else
2585 {
developerf7a466e2022-09-29 11:55:56 +08002586 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002587 return RETURN_ERR;
2588 }
2589
developerf7a466e2022-09-29 11:55:56 +08002590 params[0].name = "vht_oper_chwidth";
2591 params[0].value = set_value;
2592 params[1].name = "he_oper_chwidth";
2593 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002594
developerf7a466e2022-09-29 11:55:56 +08002595 wifi_getMaxRadioNumber(&max_radio_num);
2596 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002597 {
developerf7a466e2022-09-29 11:55:56 +08002598 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2599 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002600 }
2601
2602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2603 return RETURN_OK;
2604}
2605
2606//Getting current radio extension channel
2607INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2608{
2609 CHAR buf[150] = {0};
2610 CHAR cmd[150] = {0};
2611 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2612 _syscmd(cmd, buf, sizeof(buf));
2613 if(NULL != strstr(buf,"HT40+"))
2614 strcpy(Value,"AboveControlChannel");
2615 else if(NULL != strstr(buf,"HT40-"))
2616 strcpy(Value,"BelowControlChannel");
2617 return RETURN_OK;
2618}
2619
2620//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2621//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.
2622INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2623{
2624 if (NULL == output_string)
2625 return RETURN_ERR;
2626
2627 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2628#if 0
2629 CHAR Value[100] = {0};
2630 if (NULL == output_string)
2631 return RETURN_ERR;
2632 if(radioIndex == 0)
2633 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2634 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2635 {
2636 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2637 if(strcmp(Value,"40MHz") == 0)
2638 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2639 else
2640 strcpy(Value,"Auto");
2641 }
2642 strcpy(output_string,Value);
2643#endif
2644
2645 return RETURN_OK;
2646}
2647
2648//Set the extension channel.
2649INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2650{
2651 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2652 struct params params={'\0'};
2653 char config_file[MAX_BUF_SIZE] = {0};
2654 char ext_channel[127]={'\0'};
2655
2656 params.name = "ht_capab";
2657
2658 if(radioIndex == 0)
2659 {
2660 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002661 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002662 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002663 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002664 else
developer3cc0f2e2022-09-15 18:25:39 +08002665 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002666 }
2667 else if(radioIndex == 1)
2668 {
2669 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002670 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002671 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002672 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002673 else
developer3cc0f2e2022-09-15 18:25:39 +08002674 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002675 }
2676
2677 params.value = ext_channel;
2678 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2679 {
2680 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2681 wifi_hostapdWrite(config_file, &params, 1);
2682 }
2683
2684 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2685 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2686 return RETURN_OK;
2687}
2688
2689//Get the guard interval value. eg "400nsec" or "800nsec"
2690//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.
2691INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2692{
developer454b9462022-09-13 15:29:16 +08002693 wifi_guard_interval_t GI;
2694
2695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2696
2697 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002698 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002699
2700 if (GI == wifi_guard_interval_400)
2701 strcpy(output_string, "400nsec");
2702 else if (GI == wifi_guard_interval_800)
2703 strcpy(output_string, "800nsec");
2704 else if (GI == wifi_guard_interval_1600)
2705 strcpy(output_string, "1600nsec");
2706 else if (GI == wifi_guard_interval_3200)
2707 strcpy(output_string, "3200nsec");
2708 else
2709 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002710
developer454b9462022-09-13 15:29:16 +08002711 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002712 return RETURN_OK;
2713}
2714
2715//Set the guard interval value.
2716INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2717{
developer454b9462022-09-13 15:29:16 +08002718 wifi_guard_interval_t GI;
2719 int ret = 0;
2720
2721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2722
2723 if (strcmp(string, "400nsec") == 0)
2724 GI = wifi_guard_interval_400;
2725 else if (strcmp(string , "800nsec") == 0 || strcmp(string, "auto") == 0)
2726 GI = wifi_guard_interval_800;
2727 else if (strcmp(string , "1600nsec") == 0)
2728 GI = wifi_guard_interval_1600;
2729 else if (strcmp(string , "3200nsec") == 0)
2730 GI = wifi_guard_interval_3200;
2731
2732 ret = wifi_setGuardInterval(radioIndex, GI);
2733
2734 if (ret == RETURN_ERR) {
2735 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2736 return RETURN_ERR;
2737 }
2738
2739 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2740 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002741}
2742
2743//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2744INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2745{
2746 if (NULL == output_int)
2747 return RETURN_ERR;
2748 *output_int=(radioIndex==0)?1:3;
2749
2750 return RETURN_OK;
2751}
2752
2753//Set the Modulation Coding Scheme index
2754INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2755{
2756 return RETURN_ERR;
2757}
2758
2759//Get supported Transmit Power list, eg : "0,25,50,75,100"
2760//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.
2761INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2762{
2763 if (NULL == output_list)
2764 return RETURN_ERR;
2765 snprintf(output_list, 64,"0,25,50,75,100");
2766 return RETURN_OK;
2767}
2768
developera5005b62022-09-13 15:43:35 +08002769//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002770//The transmite power level is in units of full power for this radio.
2771INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2772{
2773 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002774 char buf[16]={0};
2775 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002776
developera5005b62022-09-13 15:43:35 +08002777 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002778 return RETURN_ERR;
2779
developera5005b62022-09-13 15:43:35 +08002780 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 +08002781 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002782
developera5005b62022-09-13 15:43:35 +08002783 *output_ulong = strtol(buf, NULL, 10);
2784
2785 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002786 return RETURN_OK;
2787}
2788
2789//Set Transmit Power
2790//The transmite power level is in units of full power for this radio.
2791INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2792{
developera5005b62022-09-13 15:43:35 +08002793 char *support;
developer06a01d92022-09-07 16:32:39 +08002794 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002795 char buf[128]={0};
2796 char txpower_str[64] = {0};
2797 int txpower = 0;
2798 int maximum_tx = 0;
2799
2800 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002801
developera5005b62022-09-13 15:43:35 +08002802 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 +08002803 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002804 maximum_tx = strtol(buf, NULL, 10);
2805
2806 // Get the Tx power supported list and check that is the input in the list
2807 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2808 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2809 support = strtok(buf, ",");
2810 while(true)
2811 {
2812 if(support == NULL) { // input not in the list
2813 wifi_dbg_printf("Input value is invalid.\n");
2814 return RETURN_ERR;
2815 }
2816 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2817 break;
2818 }
2819 support = strtok(NULL, ",");
2820 }
2821 txpower = TransmitPower*maximum_tx/100;
2822 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2823 _syscmd(cmd, buf, sizeof(buf));
2824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002825
2826 return RETURN_OK;
2827}
2828
2829//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2830INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2831{
2832 if (NULL == Supported)
2833 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002834 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002835
2836 return RETURN_OK;
2837}
2838
2839//Get 80211h feature enable
2840INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2841{
developer3885fec2022-09-13 15:13:47 +08002842 char buf[64]={'\0'};
2843 char config_file[64] = {'\0'};
2844
2845 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2846 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002847 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002848
2849 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2850 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002851
developer3885fec2022-09-13 15:13:47 +08002852 if (strncmp(buf, "1", 1) == 0)
2853 *enable = TRUE;
2854 else
2855 *enable = FALSE;
2856
2857 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002858 return RETURN_OK;
2859}
2860
2861//Set 80211h feature enable
2862INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2863{
developer3885fec2022-09-13 15:13:47 +08002864 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2865 struct params params={'\0'};
2866 char config_file[MAX_BUF_SIZE] = {0};
2867
2868 params.name = "ieee80211h";
2869
2870 if (enable) {
2871 params.value = "1";
2872 } else {
2873 params.value = "0";
2874 }
2875
2876 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2877 wifi_hostapdWrite(config_file, &params, 1);
2878
2879 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2880 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2881 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002882}
2883
2884//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.
2885INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2886{
2887 if (NULL == output)
2888 return RETURN_ERR;
2889 *output=100;
2890
2891 return RETURN_OK;
2892}
2893
2894//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.
2895INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2896{
2897 if (NULL == output)
2898 return RETURN_ERR;
2899 *output = -99;
2900
2901 return RETURN_OK;
2902}
2903
2904INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2905{
2906 return RETURN_ERR;
2907}
2908
2909
2910//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2911INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2912{
developer5f222492022-09-13 15:21:52 +08002913 char cmd[MAX_BUF_SIZE]={'\0'};
2914 char buf[MAX_CMD_SIZE]={'\0'};
2915
2916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2917 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08002918 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002919
2920 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
2921 _syscmd(cmd, buf, sizeof(buf));
2922 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08002923
developer5f222492022-09-13 15:21:52 +08002924 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002925 return RETURN_OK;
2926}
2927
2928INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
2929{
developer5f222492022-09-13 15:21:52 +08002930 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2931 struct params params={'\0'};
2932 char buf[MAX_BUF_SIZE] = {'\0'};
2933 char config_file[MAX_BUF_SIZE] = {'\0'};
2934
2935 params.name = "beacon_int";
2936 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
2937 params.value = buf;
2938
2939 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2940 wifi_hostapdWrite(config_file, &params, 1);
2941
2942 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2944 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002945}
2946
2947//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.
2948INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
2949{
developer06a01d92022-09-07 16:32:39 +08002950 //TODO: need to revisit below implementation
2951 char *temp;
developere9d0abd2022-09-13 15:40:57 +08002952 char temp_output[128] = {0};
2953 char temp_TransmitRates[64] = {0};
2954 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08002955
2956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2957 if (NULL == output)
2958 return RETURN_ERR;
2959 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08002960 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
2961
2962 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
2963 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
2964 } else {
2965 temp = strtok(temp_TransmitRates," ");
2966 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08002967 {
developere9d0abd2022-09-13 15:40:57 +08002968 // Convert 100 kbps to Mbps
2969 temp[strlen(temp)-1]=0;
2970 if((temp[0]=='5') && (temp[1]=='\0'))
2971 {
2972 temp="5.5";
2973 }
2974 strcat(temp_output,temp);
2975 temp = strtok(NULL," ");
2976 if(temp!=NULL)
2977 {
2978 strcat(temp_output,",");
2979 }
developer06a01d92022-09-07 16:32:39 +08002980 }
developere9d0abd2022-09-13 15:40:57 +08002981 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08002982 }
developer06a01d92022-09-07 16:32:39 +08002983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002984 return RETURN_OK;
2985}
2986
2987INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
2988{
2989 char *temp;
2990 char temp1[128];
2991 char temp_output[128];
2992 char temp_TransmitRates[128];
2993 char set[128];
2994 char sub_set[128];
2995 int set_count=0,subset_count=0;
2996 int set_index=0,subset_index=0;
2997 char *token;
2998 int flag=0, i=0;
2999 struct params params={'\0'};
3000 char config_file[MAX_BUF_SIZE] = {0};
3001
3002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3003 if(NULL == TransmitRates)
3004 return RETURN_ERR;
3005 strcpy(sub_set,TransmitRates);
3006
3007 //Allow only supported Data transmit rate to be set
3008 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3009 token = strtok(sub_set,",");
3010 while( token != NULL ) /* split the basic rate to be set, by comma */
3011 {
3012 sub_set[subset_count]=atoi(token);
3013 subset_count++;
3014 token=strtok(NULL,",");
3015 }
3016 token=strtok(set,",");
3017 while(token!=NULL) /* split the supported rate by comma */
3018 {
3019 set[set_count]=atoi(token);
3020 set_count++;
3021 token=strtok(NULL,",");
3022 }
3023 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3024 {
3025 for(set_index=0;set_index < set_count;set_index++)
3026 {
3027 flag=0;
3028 if(sub_set[subset_index]==set[set_index])
3029 break;
3030 else
3031 flag=1; /* No match found */
3032 }
3033 if(flag==1)
3034 return RETURN_ERR; //If value not found return Error
3035 }
3036 strcpy(temp_TransmitRates,TransmitRates);
3037
3038 for(i=0;i<strlen(temp_TransmitRates);i++)
3039 {
3040 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3041 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3042 {
3043 continue;
3044 }
3045 else
3046 {
3047 return RETURN_ERR;
3048 }
3049 }
3050 strcpy(temp_output,"");
3051 temp = strtok(temp_TransmitRates,",");
3052 while(temp!=NULL)
3053 {
3054 strcpy(temp1,temp);
3055 if(radioIndex==1)
3056 {
3057 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3058 {
3059 return RETURN_ERR;
3060 }
3061 }
3062
3063 if(strcmp(temp,"5.5")==0)
3064 {
3065 strcpy(temp1,"55");
3066 }
3067 else
3068 {
3069 strcat(temp1,"0");
3070 }
3071 strcat(temp_output,temp1);
3072 temp = strtok(NULL,",");
3073 if(temp!=NULL)
3074 {
3075 strcat(temp_output," ");
3076 }
3077 }
3078 strcpy(TransmitRates,temp_output);
3079
3080 params.name= "basic_rates";
3081 params.value =TransmitRates;
3082
3083 wifi_dbg_printf("\n%s:",__func__);
3084 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3085 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3086 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3087 wifi_hostapdWrite(config_file,&params,1);
3088 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3089 return RETURN_OK;
3090}
3091
3092//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3093INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3094{
3095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3096 FILE *fp = NULL;
3097 char path[256] = {0}, output_string[256] = {0};
3098 int count = 0;
3099 char *interface = NULL;
3100
3101 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3102 if (fp == NULL)
3103 {
3104 printf("Failed to run command in Function %s\n", __FUNCTION__);
3105 return RETURN_ERR;
3106 }
3107 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3108 {
3109 interface = strchr(path, '=');
3110
3111 if (interface != NULL)
3112 {
3113 strcpy(output_string, interface + 1);
3114 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3115 interface_name[count] = output_string[count];
3116
3117 interface_name[count] = '\0';
3118 }
3119 }
3120 pclose(fp);
3121 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3122 return RETURN_OK;
3123}
3124
3125INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3126{
3127 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3128 output_struct->radio_BytesSent = 0;
3129 output_struct->radio_BytesReceived = 0;
3130 output_struct->radio_PacketsSent = 0;
3131 output_struct->radio_PacketsReceived = 0;
3132 output_struct->radio_ErrorsSent = 0;
3133 output_struct->radio_ErrorsReceived = 0;
3134 output_struct->radio_DiscardPacketsSent = 0;
3135 output_struct->radio_DiscardPacketsReceived = 0;
3136 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3137 return RETURN_OK;
3138}
3139
3140
3141INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3142{
3143 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3144 CHAR buf[MAX_CMD_SIZE] = {0};
3145 CHAR Value[MAX_BUF_SIZE] = {0};
3146 FILE *fp = NULL;
3147
3148 if (ifname == NULL || strlen(ifname) <= 1)
3149 return RETURN_OK;
3150
3151 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3152 system(buf);
3153
3154 fp = fopen("/tmp/Radio_Stats.txt", "r");
3155 if(fp == NULL)
3156 {
3157 printf("/tmp/Radio_Stats.txt not exists \n");
3158 return RETURN_ERR;
3159 }
3160 fclose(fp);
3161
3162 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3163 File_Reading(buf, Value);
3164 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3165
3166 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3167 File_Reading(buf, Value);
3168 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3169
3170 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3171 File_Reading(buf, Value);
3172 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3173
3174 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3175 File_Reading(buf, Value);
3176 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3177
3178 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3179 File_Reading(buf, Value);
3180 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3181
3182 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3183 File_Reading(buf, Value);
3184 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3185
3186 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3187 File_Reading(buf, Value);
3188 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3189
3190 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3191 File_Reading(buf, Value);
3192 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3193
3194 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3195 return RETURN_OK;
3196}
3197
3198INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3199{
3200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3201 CHAR buf[MAX_CMD_SIZE] = {0};
3202 FILE *fp = NULL;
3203 INT count = 0;
3204
3205 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3206 {
3207 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3208 File_Reading(buf, status);
3209 }
3210 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3211 return RETURN_OK;
3212}
3213
3214//Get detail radio traffic static info
3215INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3216{
3217
3218#if 0
3219 //ifconfig radio_x
3220 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3221 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3222 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3223 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3224
3225 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3226 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3227 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.
3228 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.
3229
3230 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3231 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].
3232 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3233 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.
3234 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
3235 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
3236 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
3237 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
3238 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
3239
3240 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
3241 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
3242 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
3243 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.
3244
3245 return RETURN_OK;
3246#endif
3247
3248 CHAR private_interface_name[MAX_BUF_SIZE] = {0}, public_interface_name[MAX_BUF_SIZE] = {0};
3249 CHAR private_interface_status[MAX_BUF_SIZE] = {0}, public_interface_status[MAX_BUF_SIZE] = {0};
3250 char buf[MAX_BUF_SIZE] = {0};
3251 char cmd[MAX_CMD_SIZE] = {0};
3252 wifi_radioTrafficStats2_t private_radioTrafficStats = {0}, public_radioTrafficStats = {0};
3253
3254 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3255 if (NULL == output_struct)
3256 return RETURN_ERR;
3257
3258 if (radioIndex == 0) //2.4GHz ?
3259 {
3260
3261 GetInterfaceName(private_interface_name, "/nvram/hostapd0.conf");
3262
3263 GetIfacestatus(private_interface_name, private_interface_status);
3264
3265 sprintf(cmd, "%s", "cat /nvram/hostapd0.conf | grep bss=");
3266 File_Reading(cmd, buf);
3267
3268 if (buf[0] == '#')
3269 {
3270 GetInterfaceName(public_interface_name, "/nvram/hostapd4.conf");
3271 }
3272 else
3273 {
3274 GetInterfaceName_virtualInterfaceName_2G(public_interface_name);
3275 }
3276
3277 GetIfacestatus(public_interface_name, public_interface_status);
3278
3279 if (strcmp(private_interface_status, "1") == 0)
3280 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
3281 else
3282 wifi_halGetIfStatsNull(&private_radioTrafficStats);
3283
3284 if (strcmp(public_interface_status, "1") == 0)
3285 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
3286 else
3287 wifi_halGetIfStatsNull(&public_radioTrafficStats);
3288 }
3289 else if (radioIndex == 1) //5GHz ?
3290 {
3291 GetInterfaceName(private_interface_name, "/nvram/hostapd1.conf");
3292 GetIfacestatus(private_interface_name, private_interface_status);
3293
3294 GetInterfaceName(public_interface_name, "/nvram/hostapd5.conf");
3295 GetIfacestatus(public_interface_name, public_interface_status);
3296
3297 if (strcmp(private_interface_status, "1") == 0)
3298 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
3299 else
3300 wifi_halGetIfStatsNull(&private_radioTrafficStats);
3301
3302 if (strcmp(public_interface_status, "1") == 0)
3303 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
3304 else
3305 wifi_halGetIfStatsNull(&public_radioTrafficStats);
3306 }
3307
3308 output_struct->radio_BytesSent = private_radioTrafficStats.radio_BytesSent + public_radioTrafficStats.radio_BytesSent;
3309 output_struct->radio_BytesReceived = private_radioTrafficStats.radio_BytesReceived + public_radioTrafficStats.radio_BytesReceived;
3310 output_struct->radio_PacketsSent = private_radioTrafficStats.radio_PacketsSent + public_radioTrafficStats.radio_PacketsSent;
3311 output_struct->radio_PacketsReceived = private_radioTrafficStats.radio_PacketsReceived + public_radioTrafficStats.radio_PacketsReceived;
3312 output_struct->radio_ErrorsSent = private_radioTrafficStats.radio_ErrorsSent + public_radioTrafficStats.radio_ErrorsSent;
3313 output_struct->radio_ErrorsReceived = private_radioTrafficStats.radio_ErrorsReceived + public_radioTrafficStats.radio_ErrorsReceived;
3314 output_struct->radio_DiscardPacketsSent = private_radioTrafficStats.radio_DiscardPacketsSent + public_radioTrafficStats.radio_DiscardPacketsSent;
3315 output_struct->radio_DiscardPacketsReceived = private_radioTrafficStats.radio_DiscardPacketsReceived + public_radioTrafficStats.radio_DiscardPacketsReceived;
3316
3317 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3318 output_struct->radio_FCSErrorCount = 0; //The number of packets that were received with a detected FCS error. This parameter is based on dot11FCSErrorCount from [Annex C/802.11-2012].
3319 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3320 output_struct->radio_PacketsOtherReceived = 0; //The number of packets that were received, but which were destined for a MAC address that is not associated with this interface.
3321 output_struct->radio_NoiseFloor = -99; //The noise floor for this radio channel where a recoverable signal can be obtained. Expressed as a signed integer in the range (-110:0). Measurement should capture all energy (in dBm) from sources other than Wi-Fi devices as well as interference from Wi-Fi devices too weak to be decoded. Measured in dBm
3322 output_struct->radio_ChannelUtilization = 35; //Percentage of time the channel was occupied by the 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
3323 output_struct->radio_ActivityFactor = 2; //Percentage of time that the radio was transmitting or receiving Wi-Fi packets to/from associated clients. Activity factor MUST include all traffic that deals with communication between the radio and clients associated to the radio as well as management overhead for the radio, including NAV timers, beacons, probe responses,time for receiving devices to send an ACK, SIFC intervals, etc. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
3324 output_struct->radio_CarrierSenseThreshold_Exceeded = 20; //Percentage of time that the radio was unable to transmit or receive Wi-Fi packets to/from associated clients due to energy detection (ED) on the channel or clear channel assessment (CCA). The metric is calculated and updated in this Parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
3325 output_struct->radio_RetransmissionMetirc = 0; //Percentage of packets that had to be re-transmitted. Multiple re-transmissions of the same packet count as one. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in percentage
3326
3327 output_struct->radio_MaximumNoiseFloorOnChannel = -1; //Maximum Noise on the channel during the measuring interval. The metric is updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
3328 output_struct->radio_MinimumNoiseFloorOnChannel = -1; //Minimum Noise on the channel. The metric is updated in this Parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
3329 output_struct->radio_MedianNoiseFloorOnChannel = -1; //Median Noise on the channel during the measuring interval. The metric is updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
3330 output_struct->radio_StatisticsStartTime = 0; //The date and time at which the collection of the current set of statistics started. This time must be updated whenever the radio statistics are reset.
3331
3332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3333
3334 return RETURN_OK;
3335}
3336
3337//Set radio traffic static Measureing rules
3338INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3339{
3340 //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
3341 // Else, save the MeasuringRate and MeasuringInterval for future usage
3342
3343 return RETURN_OK;
3344}
3345
3346//To start or stop RadioTrafficStats
3347INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3348{
3349 //zqiu: If the RadioTrafficStats process running
3350 // if(enable)
3351 // return RETURN_OK.
3352 // else
3353 // Stop RadioTrafficStats process
3354 // Else
3355 // if(enable)
3356 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3357 // else
3358 // return RETURN_OK.
3359
3360 return RETURN_OK;
3361}
3362
3363//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
3364INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3365{
3366 //zqiu: Please ignor signalIndex.
3367 if (NULL == SignalLevel)
3368 return RETURN_ERR;
3369 *SignalLevel=(radioIndex==0)?-19:-19;
3370
3371 return RETURN_OK;
3372}
3373
3374//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3375INT wifi_applyRadioSettings(INT radioIndex)
3376{
3377 return RETURN_OK;
3378}
3379
3380//Get the radio index assocated with this SSID entry
3381INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3382{
3383 if (NULL == radioIndex)
3384 return RETURN_ERR;
3385 *radioIndex=ssidIndex%2;
3386
3387 return RETURN_OK;
3388}
3389
3390//Device.WiFi.SSID.{i}.Enable
3391//Get SSID enable configuration parameters (not the SSID enable status)
3392INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3393{
3394 if (NULL == output_bool)
3395 return RETURN_ERR;
3396
3397 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3398 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3399 return wifi_getApEnable(ssidIndex, output_bool);
3400}
3401
3402//Device.WiFi.SSID.{i}.Enable
3403//Set SSID enable configuration parameters
3404INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3405{
3406 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3407 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3408 return wifi_setApEnable(ssidIndex, enable);
3409}
3410
3411//Device.WiFi.SSID.{i}.Status
3412//Get the SSID enable status
3413INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3414{
3415 char cmd[MAX_CMD_SIZE]={0};
3416 char buf[MAX_BUF_SIZE]={0};
3417 BOOL output_bool;
3418
3419 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3420 if (NULL == output_string)
3421 return RETURN_ERR;
3422 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3423 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3424
3425 wifi_getApEnable(ssidIndex,&output_bool);
3426 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3427
3428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3429 return RETURN_OK;
3430}
3431
3432// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3433INT wifi_getSSIDName(INT apIndex, CHAR *output)
3434{
3435 char config_file[MAX_BUF_SIZE] = {0};
3436
3437 if (NULL == output)
3438 return RETURN_ERR;
3439
3440 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3441 wifi_hostapdRead(config_file,"ssid",output,32);
3442
3443 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3444 return RETURN_OK;
3445}
3446
3447// Set a max 32 byte string and sets an internal variable to the SSID name
3448INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3449{
3450 char str[MAX_BUF_SIZE]={'\0'};
3451 char cmd[MAX_CMD_SIZE]={'\0'};
3452 struct params params;
3453 char config_file[MAX_BUF_SIZE] = {0};
3454
3455 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3456 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3457 return RETURN_ERR;
3458
3459 params.name = "ssid";
3460 params.value = ssid_string;
3461 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3462 wifi_hostapdWrite(config_file, &params, 1);
3463 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3465
3466 return RETURN_OK;
3467}
3468
3469//Get the BSSID
3470INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3471{
3472 char cmd[MAX_CMD_SIZE]="";
3473
3474 if (NULL == output_string)
3475 return RETURN_ERR;
3476
3477 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3478 {
3479 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3480 _syscmd(cmd, output_string, 64);
3481 return RETURN_OK;
3482 }
3483 strncpy(output_string, "\0", 1);
3484
3485 return RETURN_ERR;
3486}
3487
3488//Get the MAC address associated with this Wifi SSID
3489INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3490{
3491 wifi_getBaseBSSID(ssidIndex,output_string);
3492 return RETURN_OK;
3493}
3494
3495//Get the basic SSID traffic static info
3496//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3497//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3498INT wifi_applySSIDSettings(INT ssidIndex)
3499{
3500 BOOL status = false;
3501 char cmd[MAX_CMD_SIZE] = {0};
3502 char buf[MAX_CMD_SIZE] = {0};
3503 int apIndex, ret;
3504 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3505
3506 wifi_getApEnable(ssidIndex,&status);
3507 // Do not apply when ssid index is disabled
3508 if (status == false)
3509 return RETURN_OK;
3510
3511 /* Doing full remove and add for ssid Index
3512 * Not all hostapd options are supported with reload
3513 * for example macaddr_acl
3514 */
3515 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3516 return RETURN_ERR;
3517
3518 ret = wifi_setApEnable(ssidIndex,true);
3519
3520 /* Workaround for hostapd issue with multiple bss definitions
3521 * when first created interface will be removed
3522 * then all vaps other vaps on same phy are removed
3523 * after calling setApEnable to false readd all enabled vaps */
3524 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3525 apIndex = 2*i+radioIndex;
3526 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3527 _syscmd(cmd, buf, sizeof(buf));
3528 if(*buf == '1')
3529 wifi_setApEnable(apIndex, true);
3530 }
3531
3532 return ret;
3533}
3534
developera3c68b92022-09-13 15:27:29 +08003535struct channels_noise {
3536 int channel;
3537 int noise;
3538};
3539
3540// Return noise array for each channel
3541int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3542{
3543 FILE *f = NULL;
3544 char cmd[128] = {0};
3545 char *line = NULL;
3546 size_t len = 0;
3547 ssize_t read = 0;
3548 int tmp = 0, arr_index = -1;
3549
3550 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3551
3552 if ((f = popen(cmd, "r")) == NULL) {
3553 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3554 return RETURN_ERR;
3555 }
3556 line = malloc(sizeof(char) * 256);
3557 while((read = getline(&line, &len, f)) != -1) {
3558 sscanf(line, "%d", &tmp);
3559 if (tmp > 0) { // channel frequency, the first line must be frequency
3560 arr_index++;
3561 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3562 } else { // noise
3563 channels_noise_arr[arr_index].noise = tmp;
3564 }
3565 }
3566 free(line);
3567 pclose(f);
3568 return RETURN_OK;
3569}
3570
developer06a01d92022-09-07 16:32:39 +08003571//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3572//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3573INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3574{
developera3c68b92022-09-13 15:27:29 +08003575 int index = -1;
3576 wifi_neighbor_ap2_t *scan_array = NULL;
3577 char cmd[256]={0};
3578 char buf[128]={0};
3579 char file_name[32] = {0};
3580 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003581 char line[256] = {0};
3582 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003583 int freq=0;
3584 FILE *f = NULL;
3585 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003586 int channels_num = 0;
3587 int vht_channel_width = 0;
3588 bool get_nosie_ret = false;
3589 bool filter_enable = false;
3590 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003591
developer615510b2022-09-27 10:14:35 +08003592 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003593
3594 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3595 f = fopen(file_name, "r");
3596 if (f != NULL) {
3597 fgets(filter_SSID, sizeof(file_name), f);
3598 if (strlen(filter_SSID) != 0)
3599 filter_enable = true;
3600 fclose(f);
3601 }
3602
3603 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003604 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003605 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003606
developera3c68b92022-09-13 15:27:29 +08003607 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3608 get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer06a01d92022-09-07 16:32:39 +08003609
developera3c68b92022-09-13 15:27:29 +08003610 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 +08003611 // 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 +08003612 fprintf(stderr, "cmd: %s\n", cmd);
3613 if ((f = popen(cmd, "r")) == NULL) {
3614 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3615 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003616 }
developer615510b2022-09-27 10:14:35 +08003617 ret = fgets(line, sizeof(line), f);
3618 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003619 if(strstr(line, "BSS") != NULL) { // new neighbor info
3620 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3621 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3622 // 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 +08003623
developera3c68b92022-09-13 15:27:29 +08003624 if (!filter_BSS) {
3625 index++;
3626 wifi_neighbor_ap2_t *tmp;
3627 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3628 if (tmp == NULL) { // no more memory to use
3629 index--;
3630 wifi_dbg_printf("%s: realloc failed\n", __func__);
3631 break;
3632 }
3633 scan_array = tmp;
3634 }
3635 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3636
3637 filter_BSS = false;
3638 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3639 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3640 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3641 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3642 } else if (strstr(line, "freq") != NULL) {
3643 sscanf(line," freq: %d", &freq);
3644 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3645
3646 if (freq >= 2412 && freq <= 2484) {
3647 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3648 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3649 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3650 }
3651 else if (freq >= 5160 && freq <= 5805) {
3652 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3653 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3654 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3655 }
3656
3657 scan_array[index].ap_Noise = 0;
3658 if (get_nosie_ret) {
3659 for (int i = 0; i < channels_num; i++) {
3660 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3661 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3662 break;
3663 }
3664 }
3665 }
3666 } else if (strstr(line, "beacon interval") != NULL) {
3667 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3668 } else if (strstr(line, "signal") != NULL) {
3669 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3670 } else if (strstr(line,"SSID") != NULL) {
3671 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3672 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3673 filter_BSS = true;
3674 }
3675 } else if (strstr(line, "Supported rates") != NULL) {
3676 char SRate[80] = {0}, *tmp = NULL;
3677 memset(buf, 0, sizeof(buf));
3678 strcpy(SRate, line);
3679 tmp = strtok(SRate, ":");
3680 tmp = strtok(NULL, ":");
3681 strcpy(buf, tmp);
3682 memset(SRate, 0, sizeof(SRate));
3683
3684 tmp = strtok(buf, " \n");
3685 while (tmp != NULL) {
3686 strcat(SRate, tmp);
3687 if (SRate[strlen(SRate) - 1] == '*') {
3688 SRate[strlen(SRate) - 1] = '\0';
3689 }
3690 strcat(SRate, ",");
3691
3692 tmp = strtok(NULL, " \n");
3693 }
3694 SRate[strlen(SRate) - 1] = '\0';
3695 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3696 } else if (strstr(line, "DTIM") != NULL) {
3697 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3698 } else if (strstr(line, "VHT capabilities") != NULL) {
3699 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3700 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3701 } else if (strstr(line, "HT capabilities") != NULL) {
3702 strcat(scan_array[index].ap_SupportedStandards, ",n");
3703 strcpy(scan_array[index].ap_OperatingStandards, "n");
3704 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003705 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003706 sscanf(line," * channel width: %d", &vht_channel_width);
3707 if(vht_channel_width == 1) {
3708 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3709 } else {
3710 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3711 }
3712 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3713 continue;
3714 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003715 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003716 sscanf(line," * secondary channel offset: %s", &buf);
3717 if (!strcmp(buf, "above")) {
3718 //40Mhz +
3719 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3720 }
3721 else if (!strcmp(buf, "below")) {
3722 //40Mhz -
3723 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3724 } else {
3725 //20Mhz
3726 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3727 }
3728 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3729 continue;
3730 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003731 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3732 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3733 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003734 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3735 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003736 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003737 else
developer615510b2022-09-27 10:14:35 +08003738 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003739 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003740 if (strstr(line, "HE80/5GHz") != NULL) {
3741 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3742 ret = fgets(line, sizeof(line), f);
3743 } else
3744 continue;
developera3c68b92022-09-13 15:27:29 +08003745 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003746 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003747 }
developer615510b2022-09-27 10:14:35 +08003748 continue;
developera3c68b92022-09-13 15:27:29 +08003749 } else if (strstr(line, "WPA") != NULL) {
3750 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3751 } else if (strstr(line, "RSN") != NULL) {
3752 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3753 } else if (strstr(line, "Group cipher") != NULL) {
3754 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3755 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3756 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3757 }
3758 }
developer615510b2022-09-27 10:14:35 +08003759 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003760 }
3761
3762 if (!filter_BSS) {
3763 *output_array_size = index + 1;
3764 } else {
3765 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3766 *output_array_size = index;
3767 }
3768 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003769 pclose(f);
developer06a01d92022-09-07 16:32:39 +08003770 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003771 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003772}
3773
3774//>> Deprecated: used for old RDKB code.
3775INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3776{
3777 INT status = RETURN_ERR;
3778
3779 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3780 output_struct->wifi_PLCPErrorCount = 0;
3781 output_struct->wifi_FCSErrorCount = 0;
3782 output_struct->wifi_InvalidMACCount = 0;
3783 output_struct->wifi_PacketsOtherReceived = 0;
3784 output_struct->wifi_Noise = 0;
3785 status = RETURN_OK;
3786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3787 return status;
3788}
3789
3790INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3791{
3792 char cmd[128];
3793 char buf[1280];
3794 char *pos = NULL;
3795
3796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3797 if (NULL == output_struct)
3798 return RETURN_ERR;
3799
3800 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3801
3802 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3803 _syscmd(cmd, buf, sizeof(buf));
3804
3805 pos = buf;
3806 if ((pos = strstr(pos, "RX packets:")) == NULL)
3807 return RETURN_ERR;
3808 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3809
3810 if ((pos = strstr(pos, "TX packets:")) == NULL)
3811 return RETURN_ERR;
3812 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3813
3814 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3815 return RETURN_ERR;
3816 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3817
3818 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3819 return RETURN_ERR;
3820 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3821
3822 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3823 _syscmd(cmd, buf, sizeof(buf));
3824 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3825
3826#if 0
3827 //TODO: need to revisit below implementation
3828 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3829 char interface_name[MAX_BUF_SIZE] = {0};
3830 char interface_status[MAX_BUF_SIZE] = {0};
3831 char Value[MAX_BUF_SIZE] = {0};
3832 char buf[MAX_CMD_SIZE] = {0};
3833 char cmd[MAX_CMD_SIZE] = {0};
3834 FILE *fp = NULL;
3835
3836 if (NULL == output_struct) {
3837 return RETURN_ERR;
3838 }
3839
3840 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3841
3842 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3843 {
3844 if(apIndex == 0) //private_wifi for 2.4G
3845 {
3846 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3847 }
3848 else if(apIndex == 1) //private_wifi for 5G
3849 {
3850 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3851 }
3852 else if(apIndex == 4) //public_wifi for 2.4G
3853 {
3854 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3855 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3856 {
3857 return RETURN_ERR;
3858 }
3859 if(buf[0] == '#')//tp-link
3860 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3861 else//tenda
3862 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3863 }
3864 else if(apIndex == 5) //public_wifi for 5G
3865 {
3866 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3867 }
3868
3869 GetIfacestatus(interface_name, interface_status);
3870
3871 if(0 != strcmp(interface_status, "1"))
3872 return RETURN_ERR;
3873
3874 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3875 system(cmd);
3876
3877 fp = fopen("/tmp/SSID_Stats.txt", "r");
3878 if(fp == NULL)
3879 {
3880 printf("/tmp/SSID_Stats.txt not exists \n");
3881 return RETURN_ERR;
3882 }
3883 fclose(fp);
3884
3885 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3886 File_Reading(buf, Value);
3887 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3888
3889 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3890 File_Reading(buf, Value);
3891 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3892
3893 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3894 File_Reading(buf, Value);
3895 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3896
3897 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3898 File_Reading(buf, Value);
3899 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3900
3901 /* There is no specific parameter from caller to associate the value wifi_Associations */
3902 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3903 //_syscmd(cmd, buf, sizeof(buf));
3904 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3905 }
3906#endif
3907 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3908 return RETURN_OK;
3909}
3910
3911INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3912{
3913 char interface_name[MAX_BUF_SIZE] = {0};
3914 char interface_status[MAX_BUF_SIZE] = {0};
3915 char Value[MAX_BUF_SIZE] = {0};
3916 char buf[MAX_CMD_SIZE] = {0};
3917 char cmd[MAX_CMD_SIZE] = {0};
3918 FILE *fp = NULL;
3919
3920 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3921 if (NULL == output_struct)
3922 return RETURN_ERR;
3923
3924 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3925
3926 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3927 {
3928 if(apIndex == 0) //private_wifi for 2.4G
3929 {
3930 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3931 }
3932 else if(apIndex == 1) //private_wifi for 5G
3933 {
3934 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3935 }
3936 else if(apIndex == 4) //public_wifi for 2.4G
3937 {
3938 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3939 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3940 {
3941 return RETURN_ERR;
3942 }
3943 if(buf[0] == '#')
3944 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3945 else
3946 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3947 }
3948 else if(apIndex == 5) //public_wifi for 5G
3949 {
3950 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3951 }
3952
3953 GetIfacestatus(interface_name, interface_status);
3954
3955 if(0 != strcmp(interface_status, "1"))
3956 return RETURN_ERR;
3957
3958 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3959 system(cmd);
3960
3961 fp = fopen("/tmp/SSID_Stats.txt", "r");
3962 if(fp == NULL)
3963 {
3964 printf("/tmp/SSID_Stats.txt not exists \n");
3965 return RETURN_ERR;
3966 }
3967 fclose(fp);
3968
3969 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3970 File_Reading(buf, Value);
3971 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
3972
3973 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3974 File_Reading(buf, Value);
3975 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
3976
3977 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3978 File_Reading(buf, Value);
3979 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
3980
3981 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3982 File_Reading(buf, Value);
3983 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
3984 }
3985
3986 output_struct->wifi_UnicastPacketsSent = 0;
3987 output_struct->wifi_UnicastPacketsReceived = 0;
3988 output_struct->wifi_MulticastPacketsSent = 0;
3989 output_struct->wifi_MulticastPacketsReceived = 0;
3990 output_struct->wifi_BroadcastPacketsSent = 0;
3991 output_struct->wifi_BroadcastPacketsRecevied = 0;
3992 output_struct->wifi_UnknownPacketsReceived = 0;
3993
3994 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3995 return RETURN_OK;
3996}
3997
3998INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
3999{
4000 INT status = RETURN_ERR;
4001
4002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4003 //Below values should get updated from hal
4004 output_struct->wifi_RetransCount=0;
4005 output_struct->wifi_FailedRetransCount=0;
4006 output_struct->wifi_RetryCount=0;
4007 output_struct->wifi_MultipleRetryCount=0;
4008 output_struct->wifi_ACKFailureCount=0;
4009 output_struct->wifi_AggregatedPacketCount=0;
4010
4011 status = RETURN_OK;
4012 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4013
4014 return status;
4015}
4016
4017INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4018{
4019 INT status = RETURN_ERR;
4020 UINT index;
4021 wifi_neighbor_ap_t *pt=NULL;
4022
4023 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4024 *output_array_size=2;
4025 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4026 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4027 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4028 strcpy(pt->ap_Radio,"");
4029 strcpy(pt->ap_SSID,"");
4030 strcpy(pt->ap_BSSID,"");
4031 strcpy(pt->ap_Mode,"");
4032 pt->ap_Channel=1;
4033 pt->ap_SignalStrength=0;
4034 strcpy(pt->ap_SecurityModeEnabled,"");
4035 strcpy(pt->ap_EncryptionMode,"");
4036 strcpy(pt->ap_OperatingFrequencyBand,"");
4037 strcpy(pt->ap_SupportedStandards,"");
4038 strcpy(pt->ap_OperatingStandards,"");
4039 strcpy(pt->ap_OperatingChannelBandwidth,"");
4040 pt->ap_BeaconPeriod=1;
4041 pt->ap_Noise=0;
4042 strcpy(pt->ap_BasicDataTransferRates,"");
4043 strcpy(pt->ap_SupportedDataTransferRates,"");
4044 pt->ap_DTIMPeriod=1;
4045 pt->ap_ChannelUtilization = 1;
4046 }
4047
4048 status = RETURN_OK;
4049 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4050
4051 return status;
4052}
4053
4054//----------------- AP HAL -------------------------------
4055
4056//>> Deprecated: used for old RDKB code.
4057INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4058{
4059 if (NULL == output_ulong || NULL == output_struct)
4060 return RETURN_ERR;
4061 *output_ulong = 0;
4062 *output_struct = NULL;
4063 return RETURN_OK;
4064}
4065
4066#ifdef HAL_NETLINK_IMPL
4067static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4068 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4069 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4070 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4071 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4072 char mac_addr[20];
4073 static int count=0;
4074 int rate=0;
4075
4076 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4077
4078 nla_parse(tb,
4079 NL80211_ATTR_MAX,
4080 genlmsg_attrdata(gnlh, 0),
4081 genlmsg_attrlen(gnlh, 0),
4082 NULL);
4083
4084 if(!tb[NL80211_ATTR_STA_INFO]) {
4085 fprintf(stderr, "sta stats missing!\n");
4086 return NL_SKIP;
4087 }
4088
4089
4090 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4091 fprintf(stderr, "failed to parse nested attributes!\n");
4092 return NL_SKIP;
4093 }
4094
4095 //devIndex starts from 1
4096 if( ++count == out->wifi_devIndex )
4097 {
4098 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4099 //Getting the mac addrress
4100 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4101
4102 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4103 fprintf(stderr, "failed to parse nested rate attributes!");
4104 return NL_SKIP;
4105 }
4106
4107 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4108 if(rinfo[NL80211_RATE_INFO_BITRATE])
4109 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4110 out->wifi_devTxRate = rate/10;
4111 }
4112
4113 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4114 fprintf(stderr, "failed to parse nested rate attributes!");
4115 return NL_SKIP;
4116 }
4117
4118 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4119 if(rinfo[NL80211_RATE_INFO_BITRATE])
4120 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4121 out->wifi_devRxRate = rate/10;
4122 }
4123 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4124 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4125
4126 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4127 count = 0; //starts the count for next cycle
4128 return NL_STOP;
4129 }
4130
4131 return NL_SKIP;
4132
4133}
4134#endif
4135
4136INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4137{
4138#ifdef HAL_NETLINK_IMPL
4139 Netlink nl;
4140 char if_name[10];
4141
4142 wifi_device_info_t info;
4143 info.wifi_devIndex = devIndex;
4144
4145 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4146
4147 nl.id = initSock80211(&nl);
4148
4149 if (nl.id < 0) {
4150 fprintf(stderr, "Error initializing netlink \n");
4151 return -1;
4152 }
4153
4154 struct nl_msg* msg = nlmsg_alloc();
4155
4156 if (!msg) {
4157 fprintf(stderr, "Failed to allocate netlink message.\n");
4158 nlfree(&nl);
4159 return -2;
4160 }
4161
4162 genlmsg_put(msg,
4163 NL_AUTO_PORT,
4164 NL_AUTO_SEQ,
4165 nl.id,
4166 0,
4167 NLM_F_DUMP,
4168 NL80211_CMD_GET_STATION,
4169 0);
4170
4171 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4172 nl_send_auto(nl.socket, msg);
4173 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4174 nl_recvmsgs(nl.socket, nl.cb);
4175 nlmsg_free(msg);
4176 nlfree(&nl);
4177
4178 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4179 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4180 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4181 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4182 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4183 return RETURN_OK;
4184#else
4185 //iw utility to retrieve station information
4186#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4187#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4188#define MACFILE "/tmp/wifi_AssoMac.txt"
4189#define TXRATEFILE "/tmp/wifi_txrate.txt"
4190#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4191 FILE *file = NULL;
4192 char if_name[10] = {'\0'};
4193 char pipeCmd[256] = {'\0'};
4194 char line[256];
4195 int count,device = 0;
4196
4197 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4198
4199 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4200 file = popen(pipeCmd, "r");
4201
4202 if(file == NULL)
4203 return RETURN_ERR; //popen failed
4204
4205 fgets(line, sizeof line, file);
4206 device = atoi(line);
4207 pclose(file);
4208
4209 if(device == 0)
4210 return RETURN_ERR; //No devices are connected
4211
4212 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4213 system(pipeCmd);
4214
4215 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4216
4217 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4218
4219 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4220
4221 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4222
4223 //devIndex starts from 1, ++count
4224 if((file = fopen(SIGNALFILE, "r")) != NULL )
4225 {
4226 for(count =0;fgets(line, sizeof line, file) != NULL;)
4227 {
4228 if (++count == devIndex)
4229 {
4230 output_struct->wifi_devSignalStrength = atoi(line);
4231 break;
4232 }
4233 }
4234 fclose(file);
4235 }
4236 else
4237 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4238
4239 if((file = fopen(MACFILE, "r")) != NULL )
4240 {
4241 for(count =0;fgets(line, sizeof line, file) != NULL;)
4242 {
4243 if (++count == devIndex)
4244 {
4245 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]);
4246 break;
4247 }
4248 }
4249 fclose(file);
4250 }
4251 else
4252 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4253
4254 if((file = fopen(TXRATEFILE, "r")) != NULL )
4255 {
4256 for(count =0;fgets(line, sizeof line, file) != NULL;)
4257 {
4258 if (++count == devIndex)
4259 {
4260 output_struct->wifi_devTxRate = atoi(line);
4261 break;
4262 }
4263 }
4264 fclose(file);
4265 }
4266 else
4267 fprintf(stderr,"fopen wifi_txrate.txt failed");
4268
4269 if((file = fopen(RXRATEFILE, "r")) != NULL)
4270 {
4271 for(count =0;fgets(line, sizeof line, file) != NULL;)
4272 {
4273 if (++count == devIndex)
4274 {
4275 output_struct->wifi_devRxRate = atoi(line);
4276 break;
4277 }
4278 }
4279 fclose(file);
4280 }
4281 else
4282 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4283
4284 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4285
4286 return RETURN_OK;
4287#endif
4288}
4289
4290INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4291{
4292 if (NULL == device)
4293 return RETURN_ERR;
4294 return RETURN_OK;
4295}
4296//<<
4297
4298
4299//--------------wifi_ap_hal-----------------------------
4300//enables CTS protection for the radio used by this AP
4301INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4302{
4303 //save config and Apply instantly
4304 return RETURN_ERR;
4305}
4306
4307// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4308INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4309{
developer463d39a2022-09-13 15:32:51 +08004310 char config_file[64] = {'\0'};
4311 char buf[64] = {'\0'};
4312 struct params list;
4313
4314 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4315 list.name = "ht_coex";
4316 snprintf(buf, sizeof(buf), "%d", enable);
4317 list.value = buf;
4318
4319 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4320 wifi_hostapdWrite(config_file, &list, 1);
4321 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4322
4323 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4324
4325 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004326}
4327
4328//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4329INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4330{
developerea4bcce2022-09-13 15:26:13 +08004331 char config_file[MAX_BUF_SIZE] = {'\0'};
4332 char buf[MAX_BUF_SIZE] = {'\0'};
4333 struct params list;
4334
4335 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4336 if (threshold < 256 || threshold > 2346 )
4337 return RETURN_ERR;
4338 list.name = "fragm_threshold";
4339 snprintf(buf, sizeof(buf), "%d", threshold);
4340 list.value = buf;
4341
4342 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4343 wifi_hostapdWrite(config_file, &list, 1);
4344 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004345
developerea4bcce2022-09-13 15:26:13 +08004346 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004347
4348 return RETURN_OK;
4349}
4350
4351// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4352INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4353{
developer51a927d2022-09-13 15:42:22 +08004354 char config_file[64] = {'\0'};
4355 char cmd[128] = {'\0'};
4356 char buf[64] = {'\0'};
4357 char stbc_config[16] = {'\0'};
4358 wifi_band band;
4359 int iterator = 0;
4360 BOOL current_stbc = FALSE;
4361
4362 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4363
4364 band = wifi_index_to_band(radioIndex);
4365 if (band == band_invalid)
4366 return RETURN_ERR;
4367
4368 if (band == band_2_4)
4369 iterator = 1;
4370 else if (band == band_5)
4371 iterator = 2;
4372 else
4373 return RETURN_OK;
4374
4375 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4376
4377 // set ht and vht config
4378 for (int i = 0; i < iterator; i++) {
4379 memset(stbc_config, 0, sizeof(stbc_config));
4380 memset(cmd, 0, sizeof(cmd));
4381 memset(buf, 0, sizeof(buf));
4382 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4383 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4384 _syscmd(cmd, buf, sizeof(buf));
4385 if (strlen(buf) != 0)
4386 current_stbc = TRUE;
4387 if (current_stbc == STBC_Enable)
4388 continue;
4389
4390 if (STBC_Enable == TRUE) {
4391 // Append the STBC flags in capab config
4392 memset(cmd, 0, sizeof(cmd));
4393 if (i == 0)
4394 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4395 else
4396 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4397 _syscmd(cmd, buf, sizeof(buf));
4398 } else if (STBC_Enable == FALSE) {
4399 // Remove the STBC flags and remain other flags in capab
4400 memset(cmd, 0, sizeof(cmd));
4401 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4402 _syscmd(cmd, buf, sizeof(buf));
4403 memset(cmd, 0, sizeof(cmd));
4404 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4405 _syscmd(cmd, buf, sizeof(buf));
4406 }
4407 }
4408
4409 wifi_reloadAp(radioIndex);
4410
4411 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4412 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004413}
4414
4415// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4416INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4417{
developer54e6b9f2022-09-28 14:41:20 +08004418 char AMSDU_file_path[64] = {0};
4419
4420 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4421
4422 if(output_bool == NULL)
4423 return RETURN_ERR;
4424
4425 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4426
4427 if (access(AMSDU_file_path, F_OK) == 0)
4428 *output_bool = TRUE;
4429 else
4430 *output_bool = FALSE;
4431
4432 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4433 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004434}
4435
4436// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4437INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4438{
developer54e6b9f2022-09-28 14:41:20 +08004439 char cmd[64]={0};
4440 char buf[64]={0};
4441 char AMSDU_file_path[64] = {0};
4442
4443 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4444
4445 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4446 _syscmd(cmd, buf, sizeof(buf));
4447
4448 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4449 memset(cmd, 0, sizeof(cmd));
4450 if (amsduEnable == TRUE)
4451 sprintf(cmd, "touch %s", AMSDU_file_path);
4452 else
4453 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4454 _syscmd(cmd, buf, sizeof(buf));
4455
4456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4457 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004458}
4459
4460//P2 // outputs the number of Tx streams
4461INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4462{
developer2de97692022-09-26 14:00:03 +08004463 char buf[8] = {0};
4464 char cmd[128] = {0};
4465
4466 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4467
4468 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4469 _syscmd(cmd, buf, sizeof(buf));
4470
4471 // if there is no record, output the max number of spatial streams
4472 if (strlen(buf) == 0) {
4473 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4474 _syscmd(cmd, buf, sizeof(buf));
4475 }
4476
4477 *output_int = (INT)strtol(buf, NULL, 10);
4478
4479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4480
4481 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004482}
4483
4484//P2 // sets the number of Tx streams to an enviornment variable
4485INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4486{
developer2de97692022-09-26 14:00:03 +08004487 char cmd[128] = {0};
4488 char buf[128] = {0};
4489 char chain_mask_file[128] = {0};
4490 FILE *f = NULL;
4491
4492 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4493
4494 if (numStreams == 0) {
4495 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4496 return RETURN_ERR;
4497 }
4498 wifi_setRadioEnable(radioIndex, FALSE);
4499 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4500 _syscmd(cmd, buf, sizeof(buf));
4501
4502 if (strlen(buf) > 0) {
4503 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4504 return RETURN_ERR;
4505 }
4506 wifi_setRadioEnable(radioIndex, TRUE);
4507
4508 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4509 f = fopen(chain_mask_file, "w");
4510 if (f == NULL) {
4511 fprintf(stderr, "%s: fopen failed.\n", __func__);
4512 return RETURN_ERR;
4513 }
4514 fprintf(f, "%d", numStreams);
4515 fclose(f);
4516 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4517 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004518}
4519
4520//P2 // outputs the number of Rx streams
4521INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4522{
developer2de97692022-09-26 14:00:03 +08004523 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4524 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4525 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004526 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004527 }
4528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004529 return RETURN_OK;
4530}
4531
4532//P2 // sets the number of Rx streams to an enviornment variable
4533INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4534{
developer2de97692022-09-26 14:00:03 +08004535 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4536 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4537 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4538 return RETURN_ERR;
4539 }
4540 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004541 return RETURN_ERR;
4542}
4543
4544//Get radio RDG enable setting
4545INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4546{
4547 if (NULL == output_bool)
4548 return RETURN_ERR;
4549 *output_bool = TRUE;
4550 return RETURN_OK;
4551}
4552
4553//Get radio RDG enable setting
4554INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4555{
4556 if (NULL == output_bool)
4557 return RETURN_ERR;
4558 *output_bool = TRUE;
4559 return RETURN_OK;
4560}
4561
4562//Set radio RDG enable setting
4563INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4564{
4565 return RETURN_ERR;
4566}
4567
4568//Get radio ADDBA enable setting
4569INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4570{
4571 if (NULL == output_bool)
4572 return RETURN_ERR;
4573 *output_bool = TRUE;
4574 return RETURN_OK;
4575}
4576
4577//Set radio ADDBA enable setting
4578INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4579{
4580 return RETURN_ERR;
4581}
4582
4583//Get radio auto block ack enable setting
4584INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4585{
4586 if (NULL == output_bool)
4587 return RETURN_ERR;
4588 *output_bool = TRUE;
4589 return RETURN_OK;
4590}
4591
4592//Set radio auto block ack enable setting
4593INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4594{
4595 return RETURN_ERR;
4596}
4597
4598//Get radio 11n pure mode enable support
4599INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4600{
4601 if (NULL == output_bool)
4602 return RETURN_ERR;
4603 *output_bool = TRUE;
4604 return RETURN_OK;
4605}
4606
4607//Get radio 11n pure mode enable setting
4608INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4609{
4610 if (NULL == output_bool)
4611 return RETURN_ERR;
4612 *output_bool = TRUE;
4613 return RETURN_OK;
4614}
4615
4616//Set radio 11n pure mode enable setting
4617INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4618{
4619 return RETURN_ERR;
4620}
4621
4622//Get radio IGMP snooping enable setting
4623INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4624{
developer81bf2ed2022-09-13 15:31:14 +08004625 char cmd[128]={0};
4626 char buf[4]={0};
4627 bool bridge = FALSE, mac80211 = FALSE;
4628 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4629
4630 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004631 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004632
4633 *output_bool = FALSE;
4634
4635 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4636 _syscmd(cmd, buf, sizeof(buf));
4637 if (strncmp(buf, "1", 1) == 0)
4638 bridge = TRUE;
4639
4640 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4641 _syscmd(cmd, buf, sizeof(buf));
4642 if (strncmp(buf, "1", 1) == 0)
4643 mac80211 = TRUE;
4644
4645 if (bridge && mac80211)
4646 *output_bool = TRUE;
4647
4648 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004649 return RETURN_OK;
4650}
4651
4652//Set radio IGMP snooping enable setting
4653INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4654{
developer81bf2ed2022-09-13 15:31:14 +08004655 char cmd[128]={0};
4656 char buf[4]={0};
4657
4658 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4659
4660 // bridge
4661 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4662 _syscmd(cmd, buf, sizeof(buf));
4663
4664 // mac80211
4665 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4666 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4667 _syscmd(cmd, buf, sizeof(buf));
4668 }
4669 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4670 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004671}
4672
4673//Get the Reset count of radio
4674INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4675{
4676 if (NULL == output_int)
4677 return RETURN_ERR;
4678 *output_int = (radioIndex==0)? 1: 3;
4679
4680 return RETURN_OK;
4681}
4682
4683
4684//---------------------------------------------------------------------------------------------------
4685//
4686// Additional Wifi AP level APIs used for Access Point devices
4687//
4688//---------------------------------------------------------------------------------------------------
4689
4690// creates a new ap and pushes these parameters to the hardware
4691INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4692{
4693 char buf[1024];
4694 char cmd[128];
4695
4696 if (NULL == essid)
4697 return RETURN_ERR;
4698
4699 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4700 _syscmd(cmd, buf, sizeof(buf));
4701
4702 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4703 _syscmd(cmd, buf, sizeof(buf));
4704
4705 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4706
4707 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4708 _syscmd(cmd, buf, sizeof(buf));
4709
4710 return RETURN_OK;
4711}
4712
4713// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4714INT wifi_deleteAp(INT apIndex)
4715{
4716 char buf[1024];
4717 char cmd[128];
4718
4719 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4720 _syscmd(cmd, buf, sizeof(buf));
4721
4722 wifi_removeApSecVaribles(apIndex);
4723
4724 return RETURN_OK;
4725}
4726
4727// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4728INT wifi_getApName(INT apIndex, CHAR *output_string)
4729{
4730 if(NULL == output_string)
4731 return RETURN_ERR;
4732
4733 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4734 return RETURN_OK;
4735}
4736
4737// Outputs the index number in that corresponds to the SSID string
4738INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4739{
4740 CHAR *pos = NULL;
4741
4742 *output_int = -1;
4743 pos = strstr(inputSsidString, AP_PREFIX);
4744 if(pos)
4745 {
4746 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4747 return RETURN_OK;
4748 }
4749 return RETURN_ERR;
4750}
4751
4752INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4753{
4754 return wifi_getIndexFromName(inputSsidString, output_int);
4755}
4756
4757// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4758INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4759{
4760 char buf[MAX_BUF_SIZE] = {0};
4761 char cmd[MAX_CMD_SIZE] = {0};
4762 char config_file[MAX_BUF_SIZE] = {0};
4763
4764 if(NULL == output_string)
4765 return RETURN_ERR;
4766
4767 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4768 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4769 if((strcmp(buf,"3")==0))
4770 snprintf(output_string, 32, "WPAand11i");
4771 else if((strcmp(buf,"2")==0))
4772 snprintf(output_string, 32, "11i");
4773 else if((strcmp(buf,"1")==0))
4774 snprintf(output_string, 32, "WPA");
4775 else
4776 snprintf(output_string, 32, "None");
4777
4778 return RETURN_OK;
4779}
4780
4781// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4782INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4783{
4784 char config_file[MAX_BUF_SIZE] = {0};
4785 struct params list;
4786
4787 if (NULL == beaconTypeString)
4788 return RETURN_ERR;
4789 list.name = "wpa";
4790 list.value = "0";
4791
4792 if((strcmp(beaconTypeString,"WPAand11i")==0))
4793 list.value="3";
4794 else if((strcmp(beaconTypeString,"11i")==0))
4795 list.value="2";
4796 else if((strcmp(beaconTypeString,"WPA")==0))
4797 list.value="1";
4798
4799 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4800 wifi_hostapdWrite(config_file, &list, 1);
4801 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4802 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4803 return RETURN_OK;
4804}
4805
4806// sets the beacon interval on the hardware for this AP
4807INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4808{
developer5f222492022-09-13 15:21:52 +08004809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4810 struct params params={'\0'};
4811 char buf[MAX_BUF_SIZE] = {'\0'};
4812 char config_file[MAX_BUF_SIZE] = {'\0'};
4813
4814 params.name = "beacon_int";
4815 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4816 params.value = buf;
4817
4818 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4819 wifi_hostapdWrite(config_file, &params, 1);
4820
4821 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4822 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4823 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004824}
4825
4826INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4827{
4828 //save config and apply instantly
4829 return RETURN_ERR;
4830}
4831
4832// Get the packet size threshold supported.
4833INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4834{
4835 //save config and apply instantly
4836 if (NULL == output_bool)
4837 return RETURN_ERR;
4838 *output_bool = FALSE;
4839 return RETURN_OK;
4840}
4841
4842// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4843INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4844{
4845 char cmd[128];
4846 char buf[512];
4847
4848 if (threshold > 0)
4849 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4850 else
4851 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4852 _syscmd(cmd, buf, sizeof(buf));
4853
4854 return RETURN_OK;
4855}
4856
4857// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4858INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4859{
4860 if (NULL == output_string)
4861 return RETURN_ERR;
4862 snprintf(output_string, 32, "TKIPandAESEncryption");
4863 return RETURN_OK;
4864
4865}
4866
4867// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4868INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4869{
4870 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4871 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4872
4873 if(NULL == output_string)
4874 return RETURN_ERR;
4875
4876 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4877 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4878
4879 if(strcmp(buf,"0")==0)
4880 {
4881 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4882 snprintf(output_string, 32, "None");
4883 return RETURN_OK;
4884 }
4885 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4886 param_name = "rsn_pairwise";
4887 else if((strcmp(buf,"1")==0))
4888 param_name = "wpa_pairwise";
4889 else
4890 return RETURN_ERR;
4891 memset(output_string,'\0',32);
4892 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4893 wifi_hostapdRead(config_file,param_name,output_string,32);
4894 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4895
4896 if(strcmp(output_string,"TKIP") == 0)
4897 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4898 else if(strcmp(output_string,"CCMP") == 0)
4899 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4900 else if(strcmp(output_string,"TKIP CCMP") == 0)
4901 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4902
4903 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4904 return RETURN_OK;
4905}
4906
4907// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4908INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4909{
4910 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4911 struct params params={'\0'};
4912 char output_string[32];
4913 char config_file[MAX_BUF_SIZE] = {0};
4914
4915 memset(output_string,'\0',32);
4916 wifi_getApWpaEncryptionMode(apIndex,output_string);
4917
4918 if(strcmp(encMode, "TKIPEncryption") == 0)
4919 params.value = "TKIP";
4920 else if(strcmp(encMode,"AESEncryption") == 0)
4921 params.value = "CCMP";
4922 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4923 params.value = "TKIP CCMP";
4924
4925 if((strcmp(output_string,"WPAand11i")==0))
4926 {
4927 params.name = "wpa_pairwise";
4928 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4929 wifi_hostapdWrite(config_file, &params, 1);
4930 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4931
4932 params.name,"rsn_pairwise";
4933 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4934 wifi_hostapdWrite(config_file, &params, 1);
4935 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4936
4937 return RETURN_OK;
4938 }
4939 else if((strcmp(output_string,"11i")==0))
4940 {
4941 params.name = "rsn_pairwise";
4942 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4943 wifi_hostapdWrite(config_file, &params, 1);
4944 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4945 return RETURN_OK;
4946 }
4947 else if((strcmp(output_string,"WPA")==0))
4948 {
4949 params.name = "wpa_pairwise";
4950 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4951 wifi_hostapdWrite(config_file, &params, 1);
4952 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4953 return RETURN_OK;
4954 }
4955
4956 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4957 return RETURN_OK;
4958}
4959
4960// deletes internal security varable settings for this ap
4961INT wifi_removeApSecVaribles(INT apIndex)
4962{
4963 //TODO: remove the entry in hostapd config file
4964 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4965 //_syscmd(cmd, buf, sizeof(buf));
4966
4967 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4968 //_syscmd(cmd, buf, sizeof(buf));
4969 return RETURN_ERR;
4970}
4971
4972// changes the hardware settings to disable encryption on this ap
4973INT wifi_disableApEncryption(INT apIndex)
4974{
4975 //Apply instantly
4976 return RETURN_ERR;
4977}
4978
4979// set the authorization mode on this ap
4980// mode mapping as: 1: open, 2: shared, 4:auto
4981INT wifi_setApAuthMode(INT apIndex, INT mode)
4982{
developeraf95c502022-09-13 16:18:22 +08004983 struct params params={0};
4984 char config_file[64] = {0};
4985 int ret;
4986
4987 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4988
4989 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
4990 params.name = "auth_algs";
4991
4992 if (mode & 1 && mode & 2)
4993 params.value = "3";
4994 else if (mode & 2)
4995 params.value = "2";
4996 else if (mode & 1)
4997 params.value = "1";
4998 else
4999 params.value = "0";
5000
5001 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5002 wifi_hostapdWrite(config_file, &params, 1);
5003 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5004 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5005
5006 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005007}
5008
5009// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5010INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5011{
5012 //save to wifi config, and wait for wifi restart to apply
5013 struct params params={'\0'};
5014 char config_file[MAX_BUF_SIZE] = {0};
5015 int ret;
5016
5017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5018 if(authMode == NULL)
5019 return RETURN_ERR;
5020
5021 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5022 params.name = "wpa_key_mgmt";
5023
5024 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5025 params.value = "WPA-PSK";
5026 else if(strcmp(authMode,"EAPAuthentication") == 0)
5027 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005028 else if (strcmp(authMode, "SAEAuthentication") == 0)
5029 params.value = "SAE";
5030 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5031 params.value = "WPA-EAP-SUITE-B-192";
developer06a01d92022-09-07 16:32:39 +08005032 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5033 return RETURN_OK; //This is taken careof in beaconType
5034
5035 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5036 ret=wifi_hostapdWrite(config_file,&params,1);
5037 if(!ret)
5038 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5039 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5040
5041 return ret;
5042}
5043
5044// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5045INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5046{
5047 //save to wifi config, and wait for wifi restart to apply
5048 char BeaconType[50] = {0};
5049 char config_file[MAX_BUF_SIZE] = {0};
5050
5051 *authMode = 0;
5052 wifi_getApBeaconType(apIndex,BeaconType);
5053 printf("%s____%s \n",__FUNCTION__,BeaconType);
5054
5055 if(strcmp(BeaconType,"None") == 0)
5056 strcpy(authMode,"None");
5057 else
5058 {
5059 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5060 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5061 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5062 if(strcmp(authMode,"WPA-PSK") == 0)
5063 strcpy(authMode,"SharedAuthentication");
5064 else if(strcmp(authMode,"WPA-EAP") == 0)
5065 strcpy(authMode,"EAPAuthentication");
5066 }
5067
5068 return RETURN_OK;
5069}
5070
5071// Outputs the number of stations associated per AP
5072INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5073{
5074 char cmd[128]={0};
5075 char buf[128]={0};
5076 BOOL status = false;
5077
5078 if(apIndex > MAX_APS)
5079 return RETURN_ERR;
5080
5081 wifi_getApEnable(apIndex,&status);
5082 if (!status)
5083 return RETURN_OK;
5084
5085 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5086 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5087 _syscmd(cmd, buf, sizeof(buf));
5088 sscanf(buf,"%lu", output_ulong);
5089
5090 return RETURN_OK;
5091}
5092
5093// manually removes any active wi-fi association with the device specified on this ap
5094INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5095{
5096 char buf[126]={'\0'};
5097
5098 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5099 system(buf);
5100
5101 return RETURN_OK;
5102}
5103
5104// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5105INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5106{
5107 if(NULL == output_int)
5108 return RETURN_ERR;
5109 *output_int = apIndex%2;
5110 return RETURN_OK;
5111}
5112
5113// sets the radio index for the specific ap
5114INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5115{
5116 //set to config only and wait for wifi reset to apply settings
5117 return RETURN_ERR;
5118}
5119
5120// Get the ACL MAC list per AP
5121INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5122{
5123 char cmd[MAX_CMD_SIZE]={'\0'};
5124 int ret = 0;
5125
5126 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5127 ret = _syscmd(cmd,macArray,buf_size);
5128 if (ret != 0)
5129 return RETURN_ERR;
5130
5131 return RETURN_OK;
5132}
5133
developere6aafda2022-09-13 14:59:28 +08005134INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5135{
5136 char cmd[MAX_CMD_SIZE]={'\0'};
5137 int ret = 0;
5138
5139 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5140 ret = _syscmd(cmd,macArray,buf_size);
5141 if (ret != 0)
5142 return RETURN_ERR;
5143
5144 return RETURN_OK;
5145}
5146
5147
developer06a01d92022-09-07 16:32:39 +08005148// Get the list of stations associated per AP
5149INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5150{
5151 char cmd[128];
5152
5153 if(apIndex > 3) //Currently supporting apIndex upto 3
5154 return RETURN_ERR;
5155 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5156 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5157 _syscmd(cmd, macArray, buf_size);
5158
5159 return RETURN_OK;
5160}
5161
5162// adds the mac address to the filter list
5163//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5164INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5165{
5166 char cmd[MAX_CMD_SIZE]={'\0'};
5167 char buf[MAX_BUF_SIZE]={'\0'};
5168
5169#if 0
5170 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5171 if(_syscmd(cmd,buf,sizeof(buf)))
5172 return RETURN_ERR;
5173#endif
5174 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5175 if(_syscmd(cmd,buf,sizeof(buf)))
5176 return RETURN_ERR;
5177
5178 return RETURN_OK;
5179}
5180
5181// deletes the mac address from the filter list
5182//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5183INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5184{
5185 char cmd[MAX_CMD_SIZE]={'\0'};
5186 char buf[MAX_BUF_SIZE]={'\0'};
5187
5188#if 0
5189 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5190 if(_syscmd(cmd,buf,sizeof(buf)))
5191 return RETURN_ERR;
5192
5193#endif
5194 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5195 if(_syscmd(cmd,buf,sizeof(buf)))
5196 return RETURN_ERR;
5197
5198 return RETURN_OK;
5199}
5200
5201// outputs the number of devices in the filter list
5202INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5203{
developere6aafda2022-09-13 14:59:28 +08005204 char cmd[MAX_BUF_SIZE]={0};
5205 char buf[MAX_CMD_SIZE]={0};
5206
5207 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5208 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005209 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005210
5211 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5212 _syscmd(cmd, buf, sizeof(buf));
5213
5214 *output_uint = atoi(buf);
5215
5216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5217 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005218}
5219
5220INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5221{
5222 char cmd[128]={'\0'};
5223 char buf[128]={'\0'};
5224
5225 if(strcmp(action,"DENY")==0)
5226 {
5227 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5228 system(buf);
5229 return RETURN_OK;
5230 }
5231
5232 if(strcmp(action,"ALLOW")==0)
5233 {
5234 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5235 system(buf);
5236 return RETURN_OK;
5237 }
5238
5239 return RETURN_ERR;
5240
5241}
5242
5243// enable kick for devices on acl black list
5244INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5245{
5246 char aclArray[512] = {0}, *acl = NULL;
5247 char assocArray[512] = {0}, *asso = NULL;
5248
developere6aafda2022-09-13 14:59:28 +08005249 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005250 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5251
5252 // if there are no devices connected there is nothing to do
5253 if (strlen(assocArray) < 17)
5254 return RETURN_OK;
5255
5256 if (enable == TRUE)
5257 {
5258 //kick off the MAC which is in ACL array (deny list)
5259 acl = strtok(aclArray, "\r\n");
5260 while (acl != NULL) {
5261 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5262 wifi_kickApAssociatedDevice(apIndex, acl);
5263
5264 acl = strtok(NULL, "\r\n");
5265 }
developere6aafda2022-09-13 14:59:28 +08005266 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005267 }
5268 else
5269 {
developere6aafda2022-09-13 14:59:28 +08005270 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005271 }
5272
5273#if 0
5274 //TODO: need to revisit below implementation
5275 char aclArray[512]={0}, *acl=NULL;
5276 char assocArray[512]={0}, *asso=NULL;
5277 char buf[256]={'\0'};
5278 char action[10]={'\0'};
5279 FILE *fr=NULL;
5280 char interface[10]={'\0'};
5281 char config_file[MAX_BUF_SIZE] = {0};
5282
5283 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5284 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5285 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5286 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5287
5288 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5289 system(buf);
5290 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5291 system(buf);
5292 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5293 system(buf);
5294 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5295 system(buf);
5296 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5297 system(buf);
5298
5299 if ( enable == TRUE )
5300 {
5301 int device_count=0;
5302 strcpy(action,"DENY");
5303 //kick off the MAC which is in ACL array (deny list)
5304 acl = strtok (aclArray,",");
5305 while (acl != NULL) {
5306 if(strlen(acl)>=17)
5307 {
5308 apply_rules(apIndex, acl,action,interface);
5309 device_count++;
5310 //Register mac to be blocked ,in syscfg.db persistent storage
5311 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5312 system(buf);
5313 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5314 system(buf);
5315 system("syscfg commit");
5316
5317 wifi_kickApAssociatedDevice(apIndex, acl);
5318 }
5319 acl = strtok (NULL, ",");
5320 }
5321 }
5322 else
5323 {
5324 int device_count=0;
5325 char cmdmac[20]={'\0'};
5326 strcpy(action,"ALLOW");
5327 //kick off the MAC which is not in ACL array (allow list)
5328 acl = strtok (aclArray,",");
5329 while (acl != NULL) {
5330 if(strlen(acl)>=17)
5331 {
5332 apply_rules(apIndex, acl,action,interface);
5333 device_count++;
5334 //Register mac to be Allowed ,in syscfg.db persistent storage
5335 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5336 system(buf);
5337 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5338 system(buf);
5339 sprintf(cmdmac,"%s",acl);
5340 }
5341 acl = strtok (NULL, ",");
5342 }
5343 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5344 system(buf);
5345
5346 //Disconnect the mac which is not in ACL
5347 asso = strtok (assocArray,",");
5348 while (asso != NULL) {
5349 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5350 wifi_kickApAssociatedDevice(apIndex, asso);
5351 asso = strtok (NULL, ",");
5352 }
5353 }
5354#endif
5355 return RETURN_OK;
5356}
5357
5358INT wifi_setPreferPrivateConnection(BOOL enable)
5359{
5360 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5361 char buf[1024] = {0};
5362
5363 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5364 if(enable == TRUE)
5365 {
5366 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5367 sprintf(buf,"ifconfig %s down" ,interface_name);
5368 system(buf);
5369 memset(buf,0,sizeof(buf));
5370 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5371 sprintf(buf,"ifconfig %s down" ,interface_name);
5372 system(buf);
5373 }
5374 else
5375 {
5376 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5377 if(strcmp(ssid_cur_value,"1") == 0)
5378 wifi_RestartPrivateWifi_5G();
5379 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5380 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5381 if(strcmp(ssid_cur_value,"1") == 0)
5382 wifi_RestartHostapd_2G();
5383 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5384 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5385 if(strcmp(ssid_cur_value,"1") == 0)
5386 wifi_RestartHostapd_5G();
5387 }
5388 return RETURN_OK;
5389}
5390
5391// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5392INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5393{
5394 int items = 1;
5395 struct params list[2];
5396 char buf[MAX_BUF_SIZE] = {0};
5397 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005398 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005399
5400 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005401
developer10adcc12022-09-13 14:39:17 +08005402 if (filterMode == 0) {
5403 sprintf(buf, "%d", 0);
5404 list[0].value = buf;
5405
5406 char cmd[128], rtn[128];
5407 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5408 _syscmd(cmd, rtn, sizeof(rtn));
5409 memset(cmd,0,sizeof(cmd));
5410 // Delete deny_mac_file in hostapd configuration
5411 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5412 _syscmd(cmd, rtn, sizeof(rtn));
5413 }
5414 else if (filterMode == 1) {
5415 sprintf(buf, "%d", filterMode);
5416 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005417 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5418 list[1].name = "accept_mac_file";
5419 list[1].value = acl_file;
5420 items = 2;
developer10adcc12022-09-13 14:39:17 +08005421 } else if (filterMode == 2) {
5422 //TODO: deny_mac_file
5423 sprintf(buf, "%d", 0);
5424 list[0].value = buf;
5425 list[1].name = "deny_mac_file";
5426 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5427 list[1].value = deny_file;
5428 items = 2;
5429 } else {
5430 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005431 }
developer10adcc12022-09-13 14:39:17 +08005432
developer06a01d92022-09-07 16:32:39 +08005433 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5434 wifi_hostapdWrite(config_file, list, items);
5435
5436 return RETURN_OK;
5437
5438#if 0
5439 if(apIndex==0 || apIndex==1)
5440 {
5441 //set the filtermode
5442 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5443 system(buf);
5444 system("syscfg commit");
5445
5446 if(filterMode==0)
5447 {
5448 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5449 system(buf);
5450 return RETURN_OK;
5451 }
5452 }
5453 return RETURN_OK;
5454#endif
5455}
5456
5457// 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.
5458INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5459{
5460 return RETURN_ERR;
5461}
5462
5463// gets the vlan ID for this ap from an internal enviornment variable
5464INT wifi_getApVlanID(INT apIndex, INT *output_int)
5465{
5466 if(apIndex=0)
5467 {
5468 *output_int=100;
5469 return RETURN_OK;
5470 }
5471
5472 return RETURN_ERR;
5473}
5474
5475// sets the vlan ID for this ap to an internal enviornment variable
5476INT wifi_setApVlanID(INT apIndex, INT vlanId)
5477{
5478 //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)
5479 return RETURN_ERR;
5480}
5481
5482// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5483INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5484{
5485 snprintf(bridgeName, 32, "brlan0");
5486 snprintf(IP, 32, "10.0.0.1");
5487 snprintf(subnet, 32, "255.255.255.0");
5488
5489 return RETURN_OK;
5490}
5491
5492//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5493INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5494{
5495 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5496 return RETURN_ERR;
5497}
5498
5499// reset the vlan configuration for this ap
5500INT wifi_resetApVlanCfg(INT apIndex)
5501{
developerf5fef612022-09-20 19:38:26 +08005502 char original_config_file[64] = {0};
5503 char current_config_file[64] = {0};
5504 char buf[64] = {0};
5505 char cmd[64] = {0};
5506 char vlan_file[64] = {0};
5507 char vlan_tagged_interface[16] = {0};
5508 char vlan_bridge[16] = {0};
5509 char vlan_naming[16] = {0};
5510 struct params list[4] = {0};
5511 wifi_band band;
5512
5513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5514
5515 band = wifi_index_to_band(apIndex);
5516 if (band == band_2_4)
5517 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5518 else if (band = band_5)
5519 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5520 else if (band = band_6)
5521 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5522
5523 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5524
5525 if (strlen(vlan_file) == 0)
5526 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005527
developerf5fef612022-09-20 19:38:26 +08005528 // The file should exist or this vap would not work.
5529 if (access(vlan_file, F_OK) != 0) {
5530 sprintf(cmd, "touch %s", vlan_file);
5531 _syscmd(cmd, buf, sizeof(buf));
5532 }
5533 list[0].name = "vlan_file";
5534 list[0].value = vlan_file;
5535
5536 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5537 list[1].name = "vlan_tagged_interface";
5538 list[1].value = vlan_tagged_interface;
5539
5540 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5541 list[2].name = "vlan_bridge";
5542 list[2].value = vlan_bridge;
5543
5544 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5545 list[3].name = "vlan_naming";
5546 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005547
developerf5fef612022-09-20 19:38:26 +08005548 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5549 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005550 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005551 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005552
developerf5fef612022-09-20 19:38:26 +08005553 // restart this ap
5554 wifi_setApEnable(apIndex, FALSE);
5555 wifi_setApEnable(apIndex, TRUE);
5556
5557 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5558
5559 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005560}
5561
5562// 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.
5563INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5564{
5565 return RETURN_ERR;
5566}
5567
5568// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5569INT wifi_startHostApd()
5570{
5571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5572 system("systemctl start hostapd.service");
5573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5574 return RETURN_OK;
5575 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5576}
5577
5578// stops hostapd
5579INT wifi_stopHostApd()
5580{
5581 char cmd[128] = {0};
5582 char buf[128] = {0};
5583
5584 sprintf(cmd,"systemctl stop hostapd");
5585 _syscmd(cmd, buf, sizeof(buf));
5586
5587 return RETURN_OK;
5588}
5589
5590// restart hostapd dummy function
5591INT wifi_restartHostApd()
5592{
5593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5594 system("systemctl restart hostapd-global");
5595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5596
5597 return RETURN_OK;
5598}
5599
5600static int align_hostapd_config(int index)
5601{
5602 ULONG lval;
5603 wifi_getRadioChannel(index%2, &lval);
5604 wifi_setRadioChannel(index%2, lval);
5605}
5606
5607// sets the AP enable status variable for the specified ap.
5608INT wifi_setApEnable(INT apIndex, BOOL enable)
5609{
5610 char config_file[MAX_BUF_SIZE] = {0};
5611 char cmd[MAX_CMD_SIZE] = {0};
5612 char buf[MAX_BUF_SIZE] = {0};
5613 BOOL status;
5614
5615 wifi_getApEnable(apIndex,&status);
5616 if (enable == status)
5617 return RETURN_OK;
5618
5619 if (enable == TRUE) {
5620 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5621 align_hostapd_config(apIndex);
5622 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5623 //Hostapd will bring up this interface
5624 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5625 _syscmd(cmd, buf, sizeof(buf));
5626 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5627 _syscmd(cmd, buf, sizeof(buf));
5628 }
5629 else {
5630 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5631 _syscmd(cmd, buf, sizeof(buf));
5632 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5633 _syscmd(cmd, buf, sizeof(buf));
5634 }
5635 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5636 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5637 _syscmd(cmd, buf, sizeof(buf));
5638 //Wait for wifi up/down to apply
5639 return RETURN_OK;
5640}
5641
5642// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5643INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5644{
5645 char cmd[MAX_CMD_SIZE] = {'\0'};
5646 char buf[MAX_BUF_SIZE] = {'\0'};
5647
5648 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5649 return RETURN_ERR;
5650
5651 *output_bool = 0;
5652
5653 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5654 {
developer70490032022-09-13 15:45:20 +08005655 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005656 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5657 }
5658
5659 return RETURN_OK;
5660}
5661
5662// Outputs the AP "Enabled" "Disabled" status from driver
5663INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5664{
5665 char cmd[128] = {0};
5666 char buf[128] = {0};
5667 BOOL output_bool;
5668
5669 if ( NULL == output_string)
5670 return RETURN_ERR;
5671 wifi_getApEnable(apIndex,&output_bool);
5672
5673 if(output_bool == 1)
5674 snprintf(output_string, 32, "Up");
5675 else
5676 snprintf(output_string, 32, "Disable");
5677
5678 return RETURN_OK;
5679}
5680
5681//Indicates whether or not beacons include the SSID name.
5682// outputs a 1 if SSID on the AP is enabled, else outputs 0
5683INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5684{
5685 //get the running status
5686 char config_file[MAX_BUF_SIZE] = {0};
5687 char buf[16] = {0};
5688
5689 if (!output)
5690 return RETURN_ERR;
5691
5692 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5693 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5694 *output = (strncmp("0",buf,1) == 0);
5695
5696 return RETURN_OK;
5697}
5698
5699// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5700INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5701{
5702 //store the config, apply instantly
5703 char config_file[MAX_BUF_SIZE] = {0};
5704 struct params list;
5705
5706 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5707 list.name = "ignore_broadcast_ssid";
5708 list.value = enable?"0":"1";
5709
5710 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5711 wifi_hostapdWrite(config_file, &list, 1);
5712 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5713 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005714 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005715 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5716
5717 return RETURN_OK;
5718}
5719
5720//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5721INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5722{
5723 //get the running status
5724 if(!output_uint)
5725 return RETURN_ERR;
5726 *output_uint=16;
5727 return RETURN_OK;
5728}
5729
5730INT wifi_setApRetryLimit(INT apIndex, UINT number)
5731{
5732 //apply instantly
5733 return RETURN_ERR;
5734}
5735
5736//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5737INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5738{
5739 if(!output)
5740 return RETURN_ERR;
5741 *output=TRUE;
5742 return RETURN_OK;
5743}
5744
5745//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5746INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5747{
5748 //get the running status from driver
5749 if(!output)
5750 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005751
5752 char config_file[MAX_BUF_SIZE] = {0};
5753 char buf[16] = {0};
5754
5755 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5756 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
5757 if (strncmp("1",buf,1) == 0)
5758 *output = TRUE;
5759 else
5760 *output = FALSE;
5761
developer06a01d92022-09-07 16:32:39 +08005762 return RETURN_OK;
5763}
5764
5765//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5766INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5767{
5768 //get the running status from driver
5769 if(!output)
5770 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005771
5772 char config_file[MAX_BUF_SIZE] = {0};
5773 char buf[16] = {0};
5774
5775 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5776 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5777 if (strncmp("1",buf,1) == 0)
5778 *output = TRUE;
5779 else
5780 *output = FALSE;
5781
developer06a01d92022-09-07 16:32:39 +08005782 return RETURN_OK;
5783}
5784
5785// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5786INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5787{
5788 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005789 char config_file[MAX_BUF_SIZE] = {0};
5790 struct params list;
5791
5792 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5793 list.name = "wmm_enabled";
5794 list.value = enable?"1":"0";
5795
5796 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5797 wifi_hostapdWrite(config_file, &list, 1);
5798 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5799 wifi_reloadAp(apIndex);
5800 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5801
5802 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005803}
5804
5805//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.
5806INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5807{
5808 //get the running status from driver
5809 if(!output)
5810 return RETURN_ERR;
5811 *output=TRUE;
5812 return RETURN_OK;
5813}
5814
5815// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5816INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5817{
5818 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005819 char config_file[MAX_BUF_SIZE] = {0};
5820 struct params list;
5821
5822 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5823 list.name = "uapsd_advertisement_enabled";
5824 list.value = enable?"1":"0";
5825
5826 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5827 wifi_hostapdWrite(config_file, &list, 1);
5828 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5829 wifi_reloadAp(apIndex);
5830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5831
5832 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005833}
5834
5835// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
5836INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5837{
5838 //save config and apply instantly.
5839 return RETURN_ERR;
5840}
5841
5842//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.
5843INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5844{
5845 //get the running status from driver
5846 if(!output_uint)
5847 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005848
5849 char output[16]={'\0'};
5850 char config_file[MAX_BUF_SIZE] = {0};
5851
5852 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5853 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5854 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5855 else {
5856 int device_num = atoi(output);
5857 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5858 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5859 return RETURN_ERR;
5860 }
5861 else {
5862 *output_uint = device_num;
5863 }
5864 }
5865
developer06a01d92022-09-07 16:32:39 +08005866 return RETURN_OK;
5867}
5868
5869INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5870{
5871 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005872 char str[MAX_BUF_SIZE]={'\0'};
5873 char cmd[MAX_CMD_SIZE]={'\0'};
5874 struct params params;
5875 char config_file[MAX_BUF_SIZE] = {0};
5876
5877 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5878 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5879 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5880 return RETURN_ERR;
5881 }
5882 sprintf(str, "%d", number);
5883 params.name = "max_num_sta";
5884 params.value = str;
5885
5886 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5887 int ret = wifi_hostapdWrite(config_file, &params, 1);
5888 if (ret) {
5889 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5890 ,__func__, ret);
5891 }
5892
5893 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5894 if (ret) {
5895 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5896 ,__func__, ret);
5897 }
5898 wifi_reloadAp(apIndex);
5899 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5900
5901 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005902}
5903
5904//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.
5905INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5906{
5907 //get the current threshold
5908 if(!output_uint)
5909 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005910 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5911 if (*output_uint == 0)
5912 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08005913 return RETURN_OK;
5914}
5915
5916INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
5917{
5918 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08005919 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
5920 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005921 return RETURN_ERR;
5922}
5923
5924//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.
5925INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
5926{
5927 if(!output_uint)
5928 return RETURN_ERR;
5929 *output_uint = 3;
5930 return RETURN_OK;
5931}
5932
5933//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
5934INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
5935{
5936 if(!output_uint)
5937 return RETURN_ERR;
5938 *output_uint = 3;
5939 return RETURN_OK;
5940}
5941
5942//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.
5943INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
5944{
5945 if(!output_in_seconds)
5946 return RETURN_ERR;
5947 *output_in_seconds = 0;
5948 return RETURN_OK;
5949}
5950
5951//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
5952INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
5953{
5954 if(!output || apIndex>=MAX_APS)
5955 return RETURN_ERR;
5956 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08005957 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08005958 return RETURN_OK;
5959}
5960
5961//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
5962INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
5963{
developer587c1b62022-09-27 15:58:59 +08005964 char config_file[128] = {0};
5965 char wpa[16] = {0};
5966 char key_mgmt[64] = {0};
5967 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005968 if (!output)
5969 return RETURN_ERR;
5970
5971 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08005972 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08005973
developer587c1b62022-09-27 15:58:59 +08005974 strcpy(output, "None");//Copying "None" to output string for default case
5975 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
5976 if (strstr(key_mgmt, "WPA-PSK")) {
5977 if (strcmp(wpa, "1"))
5978 snprintf(output, 32, "WPA-Personal");
5979 else if (strcmp(wpa, "2"))
5980 snprintf(output, 32, "WPA2-Personal");
5981 else if (strcmp(wpa, "3"))
5982 snprintf(output, 32, "WPA-WPA2-Personal");
5983
5984 } else if (strstr(key_mgmt, "WPA-EAP")) {
5985 if (strcmp(wpa, "1"))
5986 snprintf(output, 32, "WPA-Enterprise");
5987 else if (strcmp(wpa, "2"))
5988 snprintf(output, 32, "WPA2-Enterprise");
5989 else if (strcmp(wpa, "3"))
5990 snprintf(output, 32, "WPA-WPA2-Enterprise");
5991 } else if (strstr(key_mgmt, "SAE")) {
5992 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
5993 int disable = strtol(buf, NULL, 16);
5994 if (disable & 0x1)
5995 snprintf(output, 32, "WPA3-Personal");
5996 else
5997 snprintf(output, 32, "WPA3-Transition");
5998 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
5999 snprintf(output, 32, "WPA3-Enterprise");
6000 }
developer06a01d92022-09-07 16:32:39 +08006001
6002 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6003 return RETURN_OK;
6004#if 0
6005 //TODO: need to revisit below implementation
6006 char securityType[32], authMode[32];
6007 int enterpriseMode=0;
6008
6009 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6010 if(!output)
6011 return RETURN_ERR;
6012
6013 wifi_getApBeaconType(apIndex, securityType);
6014 strcpy(output,"None");//By default, copying "None" to output string
6015 if (strncmp(securityType,"None", strlen("None")) == 0)
6016 return RETURN_OK;
6017
6018 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6019 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6020
6021 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6022 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6023 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6024 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6025 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6026 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6027 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6028
6029 return RETURN_OK;
6030#endif
6031}
6032
6033INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6034{
6035 char securityType[32];
6036 char authMode[32];
6037
6038 //store settings and wait for wifi up to apply
6039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6040 if(!encMode)
6041 return RETURN_ERR;
6042
developer06a01d92022-09-07 16:32:39 +08006043 if (strcmp(encMode, "None")==0)
6044 {
6045 strcpy(securityType,"None");
6046 strcpy(authMode,"None");
6047 }
6048 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6049 {
6050 strcpy(securityType,"WPAand11i");
6051 strcpy(authMode,"PSKAuthentication");
6052 }
6053 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6054 {
6055 strcpy(securityType,"WPAand11i");
6056 strcpy(authMode,"EAPAuthentication");
6057 }
6058 else if (strcmp(encMode, "WPA-Personal")==0)
6059 {
6060 strcpy(securityType,"WPA");
6061 strcpy(authMode,"PSKAuthentication");
6062 }
6063 else if (strcmp(encMode, "WPA-Enterprise")==0)
6064 {
6065 strcpy(securityType,"WPA");
6066 strcpy(authMode,"EAPAuthentication");
6067 }
6068 else if (strcmp(encMode, "WPA2-Personal")==0)
6069 {
6070 strcpy(securityType,"11i");
6071 strcpy(authMode,"PSKAuthentication");
6072 }
6073 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6074 {
6075 strcpy(securityType,"11i");
6076 strcpy(authMode,"EAPAuthentication");
6077 }
developer587c1b62022-09-27 15:58:59 +08006078 else if (strcmp(encMode, "WPA3-Personal") == 0)
6079 {
6080 strcpy(securityType,"11i");
6081 strcpy(authMode,"SAEAuthentication");
6082 }
6083 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6084 {
6085 strcpy(securityType,"11i");
6086 strcpy(authMode,"EAP_192-bit_Authentication");
6087 }
developer06a01d92022-09-07 16:32:39 +08006088 else
6089 {
6090 strcpy(securityType,"None");
6091 strcpy(authMode,"None");
6092 }
6093 wifi_setApBeaconType(apIndex, securityType);
6094 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6096
6097 return RETURN_OK;
6098}
6099
6100
6101//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6102// output_string must be pre-allocated as 64 character string by caller
6103// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6104INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6105{
6106 char buf[16];
6107 char config_file[MAX_BUF_SIZE] = {0};
6108
6109 if(output_string==NULL)
6110 return RETURN_ERR;
6111
6112 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6113 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6114
6115 if(strcmp(buf,"0")==0)
6116 {
6117 printf("wpa_mode is %s ......... \n",buf);
6118 return RETURN_ERR;
6119 }
6120
6121 wifi_dbg_printf("\nFunc=%s\n",__func__);
6122 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6123 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6124 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6125
6126 return RETURN_OK;
6127}
6128
6129// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6130// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6131INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6132{
6133 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6134 struct params params={'\0'};
6135 int ret;
6136 char config_file[MAX_BUF_SIZE] = {0};
6137
6138 if(NULL == preSharedKey)
6139 return RETURN_ERR;
6140
6141 params.name = "wpa_passphrase";
6142
6143 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6144 {
6145 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6146 return RETURN_ERR;
6147 }
6148 params.value = preSharedKey;
6149 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6150 ret = wifi_hostapdWrite(config_file, &params, 1);
6151 if(!ret)
6152 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6153 return ret;
6154 //TODO: call hostapd_cli for dynamic_config_control
6155}
6156
6157//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6158// outputs the passphrase, maximum 63 characters
6159INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6160{
6161 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6162
6163 wifi_dbg_printf("\nFunc=%s\n",__func__);
6164 if (NULL == output_string)
6165 return RETURN_ERR;
6166
6167 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6168 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6169 if(strcmp(buf,"0")==0)
6170 {
6171 printf("wpa_mode is %s ......... \n",buf);
6172 return RETURN_ERR;
6173 }
6174
6175 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6176 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6177
6178 return RETURN_OK;
6179}
6180
6181// sets the passphrase enviornment variable, max 63 characters
6182INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6183{
6184 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6185 struct params params={'\0'};
6186 char config_file[MAX_BUF_SIZE] = {0};
6187 int ret;
6188
6189 if(NULL == passPhrase)
6190 return RETURN_ERR;
6191
6192 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6193 {
6194 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6195 return RETURN_ERR;
6196 }
6197 params.name = "wpa_passphrase";
6198 params.value = passPhrase;
6199 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6200 ret=wifi_hostapdWrite(config_file,&params,1);
6201 if(!ret)
6202 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6203
6204 return ret;
6205}
6206
6207//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.
6208INT wifi_setApSecurityReset(INT apIndex)
6209{
developer8d583982022-09-20 11:28:22 +08006210 char original_config_file[64] = {0};
6211 char current_config_file[64] = {0};
6212 char buf[64] = {0};
6213 char cmd[64] = {0};
6214 char wpa[4] = {0};
6215 char wpa_psk[64] = {0};
6216 char wpa_passphrase[64] = {0};
6217 char wpa_psk_file[128] = {0};
6218 char wpa_key_mgmt[64] = {0};
6219 char wpa_pairwise[32] = {0};
6220 wifi_band band;
6221 struct params list[6];
6222
6223 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6224
6225 band = wifi_index_to_band(apIndex);
6226 if (band == band_2_4)
6227 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6228 else if (band = band_5)
6229 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6230 else if (band = band_6)
6231 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6232 else
6233 return RETURN_ERR;
6234
6235 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6236 list[0].name = "wpa";
6237 list[0].value = wpa;
6238
6239 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6240 list[1].name = "wpa_psk";
6241 list[1].value = wpa_psk;
6242
6243 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6244 list[2].name = "wpa_passphrase";
6245 list[2].value = wpa_passphrase;
6246
6247 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6248
6249 if (strlen(wpa_psk_file) == 0)
6250 strcpy(wpa_psk_file, PSK_FILE);
6251
6252 if (access(wpa_psk_file, F_OK) != 0) {
6253 sprintf(cmd, "touch %s", wpa_psk_file);
6254 _syscmd(cmd, buf, sizeof(buf));
6255 }
6256 list[3].name = "wpa_psk_file";
6257 list[3].value = wpa_psk_file;
6258
6259 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6260 list[4].name = "wpa_key_mgmt";
6261 list[4].value = wpa_key_mgmt;
6262
6263 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6264 list[5].name = "wpa_pairwise";
6265 list[5].value = wpa_pairwise;
6266
6267 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6268 wifi_hostapdWrite(current_config_file, list, 6);
6269
6270 wifi_setApEnable(apIndex, FALSE);
6271 wifi_setApEnable(apIndex, TRUE);
6272
6273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6274 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006275}
6276
6277//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).
6278INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6279{
developer8f2ddd52022-09-13 15:39:24 +08006280 char config_file[64] = {0};
6281 char buf[64] = {0};
6282 char cmd[256] = {0};
6283
6284 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6285
developer06a01d92022-09-07 16:32:39 +08006286 if(!IP_output || !Port_output || !RadiusSecret_output)
6287 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006288
developer8f2ddd52022-09-13 15:39:24 +08006289 // Read the first matched config
6290 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6291 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6292 _syscmd(cmd, buf, sizeof(buf));
6293 strncpy(IP_output, buf, 64);
6294
6295 memset(buf, 0, sizeof(buf));
6296 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6297 _syscmd(cmd, buf, sizeof(buf));
6298 *Port_output = atoi(buf);
6299
6300 memset(buf, 0, sizeof(buf));
6301 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6302 _syscmd(cmd, buf, sizeof(buf));
6303 strncpy(RadiusSecret_output, buf, 64);
6304
6305 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006306 return RETURN_OK;
6307}
6308
6309INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6310{
developer8f2ddd52022-09-13 15:39:24 +08006311 char config_file[64] = {0};
6312 char port_str[8] = {0};
6313 char cmd[256] = {0};
6314 char buf[128] = {0};
6315
6316 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6317
6318 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6319
6320 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6321 _syscmd(cmd, buf, sizeof(buf));
6322 memset(cmd, 0, sizeof(cmd));
6323
6324 snprintf(port_str, sizeof(port_str), "%d", port);
6325 if (strlen(buf) == 0)
6326 // Append
6327 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6328 "auth_server_addr=%s\\n"
6329 "auth_server_port=%s\\n"
6330 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6331 else {
6332 // Delete the three lines setting after the "# radius 1" comment
6333 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6334 _syscmd(cmd, buf, sizeof(buf));
6335 memset(cmd, 0, sizeof(cmd));
6336 // Use "# radius 1" comment to find the location to insert the radius setting
6337 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6338 "# radius 1\\n"
6339 "auth_server_addr=%s\\n"
6340 "auth_server_port=%s\\n"
6341 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6342 }
6343 if(_syscmd(cmd, buf, sizeof(buf))) {
6344 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6345 return RETURN_ERR;
6346 }
6347
6348 wifi_reloadAp(apIndex);
6349 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6350 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006351}
6352
6353INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6354{
developer8f2ddd52022-09-13 15:39:24 +08006355 char config_file[64] = {0};
6356 char buf[64] = {0};
6357 char cmd[256] = {0};
6358
6359 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6360
developer06a01d92022-09-07 16:32:39 +08006361 if(!IP_output || !Port_output || !RadiusSecret_output)
6362 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006363
6364 // Read the second matched config
6365 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6366 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6367 _syscmd(cmd, buf, sizeof(buf));
6368 strncpy(IP_output, buf, 64);
6369
6370 memset(buf, 0, sizeof(buf));
6371 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6372 _syscmd(cmd, buf, sizeof(buf));
6373 *Port_output = atoi(buf);
6374
6375 memset(buf, 0, sizeof(buf));
6376 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6377 _syscmd(cmd, buf, sizeof(buf));
6378 strncpy(RadiusSecret_output, buf, 64);
6379
6380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006381 return RETURN_OK;
6382}
6383
6384INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6385{
developer8f2ddd52022-09-13 15:39:24 +08006386 char config_file[64] = {0};
6387 char port_str[8] = {0};
6388 char cmd[256] = {0};
6389 char buf[128] = {0};
6390
6391 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6392
6393 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6394
6395 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6396 _syscmd(cmd, buf, sizeof(buf));
6397 memset(cmd, 0, sizeof(cmd));
6398
6399 snprintf(port_str, sizeof(port_str), "%d", port);
6400 if (strlen(buf) == 0)
6401 // Append
6402 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6403 "auth_server_addr=%s\\n"
6404 "auth_server_port=%s\\n"
6405 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6406 else {
6407 // Delete the three lines setting after the "# radius 2" comment
6408 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6409 _syscmd(cmd, buf, sizeof(buf));
6410 memset(cmd, 0, sizeof(cmd));
6411 // Use "# radius 2" comment to find the location to insert the radius setting
6412 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6413 "# radius 2\\n"
6414 "auth_server_addr=%s\\n"
6415 "auth_server_port=%s\\n"
6416 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6417 }
6418 if(_syscmd(cmd, buf, sizeof(buf))) {
6419 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6420 return RETURN_ERR;
6421 }
6422
6423 wifi_reloadAp(apIndex);
6424 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6425 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006426}
6427
6428//RadiusSettings
6429INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6430{
6431 if(!output)
6432 return RETURN_ERR;
6433
6434 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6435 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6436 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6437 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6438 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6439 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.
6440 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6441 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6442 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6443 //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.
6444
6445 return RETURN_OK;
6446}
6447
6448INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6449{
6450 //store the paramters, and apply instantly
6451 return RETURN_ERR;
6452}
6453
6454//Device.WiFi.AccessPoint.{i}.WPS.Enable
6455//Enables or disables WPS functionality for this access point.
6456// outputs the WPS enable state of this ap in output_bool
6457INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6458{
6459 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6460 if(!output_bool || !(apIndex==0 || apIndex==1))
6461 return RETURN_ERR;
6462 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6463 _syscmd(cmd, buf, sizeof(buf));
6464 if(strstr(buf, "configured"))
6465 *output_bool=TRUE;
6466 else
6467 *output_bool=FALSE;
6468
6469 return RETURN_OK;
6470}
6471
6472//Device.WiFi.AccessPoint.{i}.WPS.Enable
6473// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6474INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6475{
6476 char config_file[MAX_BUF_SIZE] = {0};
6477 struct params params;
6478
6479 if(!(apIndex==0 || apIndex==1))
6480 return RETURN_ERR;
6481 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6482 //store the paramters, and wait for wifi up to apply
6483 params.name = "wps_state";
6484 params.value = enable ? "2":"0";
6485
6486 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6487 wifi_hostapdWrite(config_file, &params, 1);
6488 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6489 wifi_reloadAp(apIndex);
6490
6491 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6492 return RETURN_OK;
6493}
6494
6495//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
6496INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6497{
6498 if(!output)
6499 return RETURN_ERR;
6500 snprintf(output, 128, "PushButton,PIN");
6501 return RETURN_OK;
6502}
6503
6504//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6505//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.
6506// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6507INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6508{
6509 if(!output)
6510 return RETURN_ERR;
6511 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6512
6513 return RETURN_OK;
6514}
6515
6516//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6517// 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
6518INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6519{
6520 //apply instantly. No setting need to be stored.
6521 char methods[MAX_BUF_SIZE], *token, *next_token;
6522 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6523 struct params params;
6524
6525 if(!methodString || !(apIndex==0 || apIndex==1))
6526 return RETURN_ERR;
6527 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6528 //store the paramters, and wait for wifi up to apply
6529
6530 snprintf(methods, sizeof(methods), "%s", methodString);
6531 for(token=methods; *token; token=next_token)
6532 {
6533 strtok_r(token, ",", &next_token);
6534 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6535 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6536 else if(*token=='E')
6537 {
6538 if(!strcmp(methods, "Ethernet"))
6539 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6540 else if(!strcmp(methods, "ExternalNFCToken"))
6541 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6542 else
6543 printf("%s: Unknown WpsConfigMethod\n", __func__);
6544 }
6545 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6546 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6547 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6548 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6549 else if(*token=='P' )
6550 {
6551 if(!strcmp(token, "PushButton"))
6552 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6553 else if(!strcmp(token, "PIN"))
6554 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6555 else
6556 printf("%s: Unknown WpsConfigMethod\n", __func__);
6557 }
6558 else
6559 printf("%s: Unknown WpsConfigMethod\n", __func__);
6560 }
6561 params.name = "config_methods";
6562 params.value = config_methods;
6563 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6564 wifi_hostapdWrite(config_file, &params, 1);
6565 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6567
6568 return RETURN_OK;
6569}
6570
6571// outputs the pin value, ulong_pin must be allocated by the caller
6572INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6573{
6574 char buf[MAX_BUF_SIZE] = {0};
6575 char cmd[MAX_CMD_SIZE] = {0};
6576
6577 if(!output_ulong || !(apIndex==0 || apIndex==1))
6578 return RETURN_ERR;
6579 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6580 _syscmd(cmd, buf, sizeof(buf));
6581 if(strlen(buf) > 0)
6582 *output_ulong=strtoul(buf, NULL, 10);
6583
6584 return RETURN_OK;
6585}
6586
6587// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6588INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6589{
6590 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6591 char ap_pin[16] = {0};
6592 char buf[MAX_BUF_SIZE] = {0};
6593 char config_file[MAX_BUF_SIZE] = {0};
6594 ULONG prev_pin = 0;
6595 struct params params;
6596
6597 if(!(apIndex==0 || apIndex==1))
6598 return RETURN_ERR;
6599 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6600 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6601 params.name = "ap_pin";
6602 params.value = ap_pin;
6603 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6604 wifi_hostapdWrite(config_file, &params, 1);
6605 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6607
6608 return RETURN_OK;
6609}
6610
6611// Output string is either Not configured or Configured, max 32 characters
6612INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6613{
6614 char cmd[MAX_CMD_SIZE];
6615 char buf[MAX_BUF_SIZE]={0};
6616
6617 if(!output_string || !(apIndex==0 || apIndex==1))
6618 return RETURN_ERR;
6619 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6620 snprintf(output_string, 32, "Not configured");
6621 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6622 _syscmd(cmd, buf, sizeof(buf));
6623
developer348e3d92022-09-13 14:48:41 +08006624 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006625 snprintf(output_string, 32, "Configured");
6626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6627
6628 return RETURN_OK;
6629}
6630
6631// sets the WPS pin for this AP
6632INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6633{
6634 char cmd[MAX_CMD_SIZE];
6635 char buf[MAX_BUF_SIZE]={0};
6636 BOOL enable;
6637
6638 if(!(apIndex==0 || apIndex==1))
6639 return RETURN_ERR;
6640 wifi_getApEnable(apIndex, &enable);
6641 if (!enable)
6642 return RETURN_ERR;
6643 wifi_getApWpsEnable(apIndex, &enable);
6644 if (!enable)
6645 return RETURN_ERR;
6646
6647 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6648 _syscmd(cmd, buf, sizeof(buf));
6649 if((strstr(buf, "OK"))!=NULL)
6650 return RETURN_OK;
6651
6652 return RETURN_ERR;
6653}
6654
6655// This function is called when the WPS push button has been pressed for this AP
6656INT wifi_setApWpsButtonPush(INT apIndex)
6657{
6658 char cmd[MAX_CMD_SIZE];
6659 char buf[MAX_BUF_SIZE]={0};
6660 BOOL enable=FALSE;
6661
6662 if(!(apIndex==0 || apIndex==1))
6663 return RETURN_ERR;
6664 wifi_getApEnable(apIndex, &enable);
6665 if (!enable)
6666 return RETURN_ERR;
6667
6668 wifi_getApWpsEnable(apIndex, &enable);
6669 if (!enable)
6670 return RETURN_ERR;
6671
6672 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6673 _syscmd(cmd, buf, sizeof(buf));
6674
6675 if((strstr(buf, "OK"))!=NULL)
6676 return RETURN_OK;
6677 return RETURN_ERR;
6678}
6679
6680// cancels WPS mode for this AP
6681INT wifi_cancelApWPS(INT apIndex)
6682{
6683 char cmd[MAX_CMD_SIZE];
6684 char buf[MAX_BUF_SIZE]={0};
6685
6686 if(!(apIndex==0 || apIndex==1))
6687 return RETURN_ERR;
6688 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6689 _syscmd(cmd,buf, sizeof(buf));
6690
6691 if((strstr(buf, "OK"))!=NULL)
6692 return RETURN_OK;
6693 return RETURN_ERR;
6694}
6695
6696//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6697//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6698INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6699{
6700 FILE *f;
6701 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6702 char cmd[256], buf[2048];
6703 char *param , *value, *line=NULL;
6704 size_t len = 0;
6705 ssize_t nread;
6706 wifi_associated_dev_t *dev=NULL;
6707
6708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6709 *associated_dev_array = NULL;
6710 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6711 _syscmd(cmd,buf,sizeof(buf));
6712 *output_array_size = atoi(buf);
6713
6714 if (*output_array_size <= 0)
6715 return RETURN_OK;
6716
6717 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6718 *associated_dev_array = dev;
6719 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6720 _syscmd(cmd,buf,sizeof(buf));
6721 f = fopen("/tmp/connected_devices.txt", "r");
6722 if (f==NULL)
6723 {
6724 *output_array_size=0;
6725 return RETURN_ERR;
6726 }
6727 while ((nread = getline(&line, &len, f)) != -1)
6728 {
6729 param = strtok(line,"=");
6730 value = strtok(NULL,"=");
6731
6732 if( strcmp("flags",param) == 0 )
6733 {
6734 value[strlen(value)-1]='\0';
6735 if(strstr (value,"AUTHORIZED") != NULL )
6736 {
6737 dev[auth_temp].cli_AuthenticationState = 1;
6738 dev[auth_temp].cli_Active = 1;
6739 auth_temp++;
6740 read_flag=1;
6741 }
6742 }
6743 if(read_flag==1)
6744 {
6745 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6746 {
6747 value[strlen(value)-1]='\0';
6748 sscanf(value, "%x:%x:%x:%x:%x:%x",
6749 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6750 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6751 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6752 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6753 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6754 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6755 mac_temp++;
6756 read_flag=0;
6757 }
6758 }
6759 }
6760 *output_array_size = auth_temp;
6761 auth_temp=0;
6762 mac_temp=0;
6763 free(line);
6764 fclose(f);
6765 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6766 return RETURN_OK;
6767}
6768
6769#define MACADDRESS_SIZE 6
6770
6771INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6772{
6773 FILE *fp = NULL;
6774 char str[MAX_BUF_SIZE] = {0};
6775 int wificlientindex = 0 ;
6776 int count = 0;
6777 int signalstrength = 0;
6778 int arr[MACADDRESS_SIZE] = {0};
6779 unsigned char mac[MACADDRESS_SIZE] = {0};
6780 UINT wifi_count = 0;
6781 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6782 char pipeCmd[MAX_CMD_SIZE] = {0};
6783
6784 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6785 *output_array_size = 0;
6786 *associated_dev_array = NULL;
6787
6788 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6789 fp = popen(pipeCmd, "r");
6790 if (fp == NULL)
6791 {
6792 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6793 return RETURN_ERR;
6794 }
6795
6796 /* Read the output a line at a time - output it. */
6797 fgets(str, sizeof(str)-1, fp);
6798 wifi_count = (unsigned int) atoi ( str );
6799 *output_array_size = wifi_count;
6800 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6801 pclose(fp);
6802
6803 if(wifi_count == 0)
6804 {
6805 return RETURN_OK;
6806 }
6807 else
6808 {
6809 wifi_associated_dev3_t* temp = NULL;
6810 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6811 if(temp == NULL)
6812 {
6813 printf("Error Statement. Insufficient memory \n");
6814 return RETURN_ERR;
6815 }
6816
6817 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6818 system(pipeCmd);
6819 memset(pipeCmd,0,sizeof(pipeCmd));
6820 if(apIndex == 0)
6821 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6822 else if(apIndex == 1)
6823 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6824 system(pipeCmd);
6825
6826 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6827 if(fp == NULL)
6828 {
6829 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6830 return RETURN_ERR;
6831 }
6832 fclose(fp);
6833
6834 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6835 fp = popen(pipeCmd, "r");
6836 if(fp)
6837 {
6838 for(count =0 ; count < wifi_count; count++)
6839 {
6840 fgets(str, MAX_BUF_SIZE, fp);
6841 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6842 {
6843 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6844 {
6845 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6846
6847 }
6848 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6849 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]);
6850 }
6851 temp[count].cli_AuthenticationState = 1; //TODO
6852 temp[count].cli_Active = 1; //TODO
6853 }
6854 pclose(fp);
6855 }
6856
6857 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6858 fp = popen(pipeCmd, "r");
6859 if(fp)
6860 {
6861 pclose(fp);
6862 }
6863 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6864 if(fp)
6865 {
6866 for(count =0 ; count < wifi_count ;count++)
6867 {
6868 fgets(str, MAX_BUF_SIZE, fp);
6869 signalstrength = atoi(str);
6870 temp[count].cli_SignalStrength = signalstrength;
6871 temp[count].cli_RSSI = signalstrength;
6872 temp[count].cli_SNR = signalstrength + 95;
6873 }
6874 pclose(fp);
6875 }
6876
6877
6878 if((apIndex == 0) || (apIndex == 4))
6879 {
6880 for(count =0 ; count < wifi_count ;count++)
6881 {
6882 strcpy(temp[count].cli_OperatingStandard,"g");
6883 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6884 }
6885
6886 //BytesSent
6887 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6888 fp = popen(pipeCmd, "r");
6889 if(fp)
6890 {
6891 pclose(fp);
6892 }
6893 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6894 if(fp)
6895 {
6896 for (count = 0; count < wifi_count; count++)
6897 {
6898 fgets(str, MAX_BUF_SIZE, fp);
6899 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6900 }
6901 pclose(fp);
6902 }
6903
6904 //BytesReceived
6905 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6906 fp = popen(pipeCmd, "r");
6907 if (fp)
6908 {
6909 pclose(fp);
6910 }
6911 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6912 if (fp)
6913 {
6914 for (count = 0; count < wifi_count; count++)
6915 {
6916 fgets(str, MAX_BUF_SIZE, fp);
6917 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
6918 }
6919 pclose(fp);
6920 }
6921
6922 //PacketsSent
6923 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
6924 fp = popen(pipeCmd, "r");
6925 if (fp)
6926 {
6927 pclose(fp);
6928 }
6929
6930 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
6931 if (fp)
6932 {
6933 for (count = 0; count < wifi_count; count++)
6934 {
6935 fgets(str, MAX_BUF_SIZE, fp);
6936 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
6937 }
6938 pclose(fp);
6939 }
6940
6941 //PacketsReceived
6942 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
6943 fp = popen(pipeCmd, "r");
6944 if (fp)
6945 {
6946 pclose(fp);
6947 }
6948 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
6949 if (fp)
6950 {
6951 for (count = 0; count < wifi_count; count++)
6952 {
6953 fgets(str, MAX_BUF_SIZE, fp);
6954 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
6955 }
6956 pclose(fp);
6957 }
6958
6959 //ErrorsSent
6960 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6961 fp = popen(pipeCmd, "r");
6962 if (fp)
6963 {
6964 pclose(fp);
6965 }
6966 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6967 if (fp)
6968 {
6969 for (count = 0; count < wifi_count; count++)
6970 {
6971 fgets(str, MAX_BUF_SIZE, fp);
6972 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6973 }
6974 pclose(fp);
6975 }
6976
6977 //ErrorsSent
6978 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6979 fp = popen(pipeCmd, "r");
6980 if (fp)
6981 {
6982 pclose(fp);
6983 }
6984 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6985 if (fp)
6986 {
6987 for (count = 0; count < wifi_count; count++)
6988 {
6989 fgets(str, MAX_BUF_SIZE, fp);
6990 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6991 }
6992 pclose(fp);
6993 }
6994
6995 //LastDataDownlinkRate
6996 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
6997 fp = popen(pipeCmd, "r");
6998 if (fp)
6999 {
7000 pclose(fp);
7001 }
7002 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7003 if (fp)
7004 {
7005 for (count = 0; count < wifi_count; count++)
7006 {
7007 fgets(str, MAX_BUF_SIZE, fp);
7008 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7009 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7010 }
7011 pclose(fp);
7012 }
7013
7014 //LastDataUplinkRate
7015 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7016 fp = popen(pipeCmd, "r");
7017 if (fp)
7018 {
7019 pclose(fp);
7020 }
7021 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7022 if (fp)
7023 {
7024 for (count = 0; count < wifi_count; count++)
7025 {
7026 fgets(str, MAX_BUF_SIZE, fp);
7027 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7028 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7029 }
7030 pclose(fp);
7031 }
7032
7033 }
7034 else if ((apIndex == 1) || (apIndex == 5))
7035 {
7036 for (count = 0; count < wifi_count; count++)
7037 {
7038 strcpy(temp[count].cli_OperatingStandard, "a");
7039 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7040 temp[count].cli_BytesSent = 0;
7041 temp[count].cli_BytesReceived = 0;
7042 temp[count].cli_LastDataUplinkRate = 0;
7043 temp[count].cli_LastDataDownlinkRate = 0;
7044 temp[count].cli_PacketsSent = 0;
7045 temp[count].cli_PacketsReceived = 0;
7046 temp[count].cli_ErrorsSent = 0;
7047 }
7048 }
7049
7050 for (count = 0; count < wifi_count; count++)
7051 {
7052 temp[count].cli_Retransmissions = 0;
7053 temp[count].cli_DataFramesSentAck = 0;
7054 temp[count].cli_DataFramesSentNoAck = 0;
7055 temp[count].cli_MinRSSI = 0;
7056 temp[count].cli_MaxRSSI = 0;
7057 strncpy(temp[count].cli_InterferenceSources, "", 64);
7058 memset(temp[count].cli_IPAddress, 0, 64);
7059 temp[count].cli_RetransCount = 0;
7060 temp[count].cli_FailedRetransCount = 0;
7061 temp[count].cli_RetryCount = 0;
7062 temp[count].cli_MultipleRetryCount = 0;
7063 }
7064 *associated_dev_array = temp;
7065 }
7066 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7067 return RETURN_OK;
7068}
7069
7070int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7071{
7072 FILE *fp = NULL;
7073 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7074 char cmd[MAX_CMD_SIZE];
7075 int count = 0;
7076
7077 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7078 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7079 fp = popen(cmd,"r");
7080 if(fp == NULL)
7081 {
7082 printf("Failed to run command in Function %s\n",__FUNCTION__);
7083 return 0;
7084 }
7085 if(fgets(path, sizeof(path)-1, fp) != NULL)
7086 {
7087 for(count=0;path[count]!='\n';count++)
7088 status[count]=path[count];
7089 status[count]='\0';
7090 }
7091 strcpy(wifi_status,status);
7092 pclose(fp);
7093 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7094 return RETURN_OK;
7095}
7096
7097/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7098struct hostapd_sta_param {
7099 char key[50];
7100 char value[100];
7101}
7102
7103static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7104 int i = 0;
7105
7106 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7107 if (strncmp(params[i].key,key,50) == 0){
7108 return &params[i].value;
7109 }
7110 i++;
7111 }
7112 return NULL;
7113
7114} */
7115
7116static unsigned int count_occurences(const char *buf, const char *word)
7117{
7118 unsigned int n = 0;
7119 char *ptr = strstr(buf, word);
7120
7121 while (ptr++) {
7122 n++;
7123 ptr = strstr(ptr, word);
7124 }
7125
7126 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7127 return n;
7128}
7129
7130static const char *get_line_from_str_buf(const char *buf, char *line)
7131{
7132 int i;
7133 int n = strlen(buf);
7134
7135 for (i = 0; i < n; i++) {
7136 line[i] = buf[i];
7137 if (buf[i] == '\n') {
7138 line[i] = '\0';
7139 return &buf[i + 1];
7140 }
7141 }
7142
7143 return NULL;
7144}
7145
7146INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7147{
7148 unsigned int assoc_cnt = 0;
7149 char interface_name[50] = {0};
7150 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7151 char cmd[MAX_CMD_SIZE] = {'\0'};
7152 char line[256] = {'\0'};
7153 int i = 0;
7154 int ret = 0;
7155 const char *ptr = NULL;
7156 char *key = NULL;
7157 char *val = NULL;
7158 wifi_associated_dev3_t *temp = NULL;
7159 int rssi;
7160
7161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7162
7163 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7164 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7165 return RETURN_ERR;
7166 }
7167
7168 // Example filtered output of 'iw dev' command:
7169 // Station 0a:69:72:10:d2:fa (on wifi0)
7170 // signal avg:-67 [-71, -71] dBm
7171 // Station 28:c2:1f:25:5f:99 (on wifi0)
7172 // signal avg:-67 [-71, -70] dBm
7173 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7174 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7175 return RETURN_ERR;
7176 }
7177
7178 ret = _syscmd(cmd, buf, sizeof(buf));
7179 if (ret == RETURN_ERR) {
7180 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7181 return RETURN_ERR;
7182 }
7183
7184 *output_array_size = count_occurences(buf, "Station");
7185 if (*output_array_size == 0) return RETURN_OK;
7186
7187 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7188 if (temp == NULL) {
7189 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7190 return RETURN_ERR;
7191 }
7192 *associated_dev_array = temp;
7193
7194 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7195 ptr = get_line_from_str_buf(buf, line);
7196 i = -1;
7197 while (ptr) {
7198 if (strstr(line, "Station")) {
7199 i++;
7200 key = strtok(line, " ");
7201 val = strtok(NULL, " ");
7202 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7203 &temp[i].cli_MACAddress[0],
7204 &temp[i].cli_MACAddress[1],
7205 &temp[i].cli_MACAddress[2],
7206 &temp[i].cli_MACAddress[3],
7207 &temp[i].cli_MACAddress[4],
7208 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7209 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7210 free(*associated_dev_array);
7211 return RETURN_ERR;
7212 }
7213 }
7214 else if (i < 0) {
7215 ptr = get_line_from_str_buf(ptr, line);
7216 continue; // We didn't detect 'station' entry yet
7217 }
7218 else if (strstr(line, "signal avg")) {
7219 key = strtok(line, ":");
7220 val = strtok(NULL, " ");
7221 if (sscanf(val, "%d", &rssi) <= 0 ) {
7222 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7223 free(*associated_dev_array);
7224 return RETURN_ERR;
7225 }
7226 temp[i].cli_RSSI = rssi;
7227 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7228 }
7229 // Here other fields can be parsed if added to filter of 'iw dev' command
7230
7231 ptr = get_line_from_str_buf(ptr, line);
7232 };
7233
7234 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7235
7236 return RETURN_OK;
7237}
7238
7239#if 0
7240//To-do
7241INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7242{
7243 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7244
7245 //Using different approach to get required WiFi Parameters from system available commands
7246#if 0
7247 FILE *f;
7248 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7249 char cmd[256], buf[2048];
7250 char *param , *value, *line=NULL;
7251 size_t len = 0;
7252 ssize_t nread;
7253 wifi_associated_dev3_t *dev=NULL;
7254 *associated_dev_array = NULL;
7255 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7256 _syscmd(cmd,buf,sizeof(buf));
7257 *output_array_size = atoi(buf);
7258
7259 if (*output_array_size <= 0)
7260 return RETURN_OK;
7261
7262 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7263 *associated_dev_array = dev;
7264 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7265 _syscmd(cmd,buf,sizeof(buf));
7266 f = fopen("/tmp/connected_devices.txt", "r");
7267 if (f==NULL)
7268 {
7269 *output_array_size=0;
7270 return RETURN_ERR;
7271 }
7272 while ((nread = getline(&line, &len, f)) != -1)
7273 {
7274 param = strtok(line,"=");
7275 value = strtok(NULL,"=");
7276
7277 if( strcmp("flags",param) == 0 )
7278 {
7279 value[strlen(value)-1]='\0';
7280 if(strstr (value,"AUTHORIZED") != NULL )
7281 {
7282 dev[auth_temp].cli_AuthenticationState = 1;
7283 dev[auth_temp].cli_Active = 1;
7284 auth_temp++;
7285 read_flag=1;
7286 }
7287 }
7288 if(read_flag==1)
7289 {
7290 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7291 {
7292 value[strlen(value)-1]='\0';
7293 sscanf(value, "%x:%x:%x:%x:%x:%x",
7294 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7295 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7296 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7297 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7298 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7299 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7300
7301 }
7302 else if( strcmp("rx_packets",param) == 0 )
7303 {
7304 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7305 }
7306
7307 else if( strcmp("tx_packets",param) == 0 )
7308 {
7309 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7310 }
7311
7312 else if( strcmp("rx_bytes",param) == 0 )
7313 {
7314 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7315 }
7316
7317 else if( strcmp("tx_bytes",param) == 0 )
7318 {
7319 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7320 mac_temp++;
7321 read_flag=0;
7322 }
7323 }
7324 }
7325
7326 *output_array_size = auth_temp;
7327 auth_temp=0;
7328 mac_temp=0;
7329 free(line);
7330 fclose(f);
7331#endif
7332 char interface_name[MAX_BUF_SIZE] = {0};
7333 char wifi_status[MAX_BUF_SIZE] = {0};
7334 char hostapdconf[MAX_BUF_SIZE] = {0};
7335
7336 wifi_associated_dev3_t *dev_array = NULL;
7337 ULONG wifi_count = 0;
7338
7339 *associated_dev_array = NULL;
7340 *output_array_size = 0;
7341
7342 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7343 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7344 {
7345 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7346
7347 GetInterfaceName(interface_name, hostapdconf);
7348
7349 if(strlen(interface_name) > 1)
7350 {
7351 wifihal_interfacestatus(wifi_status,interface_name);
7352 if(strcmp(wifi_status,"RUNNING") == 0)
7353 {
7354 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7355
7356 *associated_dev_array = dev_array;
7357 *output_array_size = wifi_count;
7358 }
7359 else
7360 {
7361 *associated_dev_array = NULL;
7362 }
7363 }
7364 }
7365
7366 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7367 return RETURN_OK;
7368}
7369#endif
7370
7371/* getIPAddress function */
7372/**
7373* @description Returning IpAddress of the Matched String
7374*
7375* @param
7376* @str Having MacAddress
7377* @ipaddr Having ipaddr
7378* @return The status of the operation
7379* @retval RETURN_OK if successful
7380* @retval RETURN_ERR if any error is detected
7381*
7382*/
7383
7384INT getIPAddress(char *str,char *ipaddr)
7385{
7386 FILE *fp = NULL;
7387 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7388 int LeaseTime = 0,ret = 0;
7389 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7390 {
7391 return RETURN_ERR;
7392 }
7393
7394 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7395 {
7396 /*
7397 Sample:sss
7398 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7399 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7400 */
7401 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7402 &(LeaseTime),
7403 phyAddr,
7404 ipAddr,
7405 hostName
7406 );
7407 if(ret != 4)
7408 continue;
7409 if(strcmp(str,phyAddr) == 0)
7410 strcpy(ipaddr,ipAddr);
7411 }
7412 return RETURN_OK;
7413}
7414
7415/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7416/**
7417* @description Returning Inactive wireless connected clients informations
7418*
7419* @param
7420* @filename Holding private_wifi 2g/5g content files
7421* @associated_dev_array Having inactiv wireless clients informations
7422* @output_array_size Returning Inactive wireless counts
7423* @return The status of the operation
7424* @retval RETURN_OK if successful
7425* @retval RETURN_ERR if any error is detected
7426*
7427*/
7428
7429INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7430{
7431 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7432 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7433 FILE *fp = NULL;
7434 int arr[MACADDRESS_SIZE] = {0};
7435 unsigned char mac[MACADDRESS_SIZE] = {0};
7436 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7437 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7438 fp = popen(buf,"r");
7439 if(fp == NULL)
7440 return RETURN_ERR;
7441 else
7442 {
7443 fgets(path,sizeof(path),fp);
7444 maccount = atoi(path);
7445 }
7446 pclose(fp);
7447 *output_array_size = maccount;
7448 wifi_associated_dev3_t* temp = NULL;
7449 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7450 *associated_dev_array = temp;
7451 if(temp == NULL)
7452 {
7453 printf("Error Statement. Insufficient memory \n");
7454 return RETURN_ERR;
7455 }
7456 memset(buf,0,sizeof(buf));
7457 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7458 fp = popen(buf,"r");
7459 for(count = 0; count < maccount ; count++)
7460 {
7461 fgets(path,sizeof(path),fp);
7462 for(i = 0; path[i]!='\n';i++)
7463 str[i]=path[i];
7464 str[i]='\0';
7465 getIPAddress(str,ipaddr);
7466 memset(buf,0,sizeof(buf));
7467 if(strlen(ipaddr) > 0)
7468 {
7469 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7470 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7471 {
7472 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7473 {
7474 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7475 {
7476 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7477
7478 }
7479 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7480 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]);
7481 }
7482 temp[count].cli_AuthenticationState = 0; //TODO
7483 temp[count].cli_Active = 0; //TODO
7484 temp[count].cli_SignalStrength = 0;
7485 }
7486 else //Active wireless clients info
7487 {
7488 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7489 {
7490 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7491 {
7492 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7493
7494 }
7495 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7496 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]);
7497 }
7498 temp[count].cli_Active = 1;
7499 }
7500 }
7501 memset(ipaddr,0,sizeof(ipaddr));
7502 }
7503 pclose(fp);
7504 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7505 return RETURN_OK;
7506}
7507//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7508//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7509//To get Band Steering Capability
7510INT wifi_getBandSteeringCapability(BOOL *support)
7511{
7512 *support = FALSE;
7513 return RETURN_OK;
7514}
7515
7516
7517//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7518//To get Band Steering enable status
7519INT wifi_getBandSteeringEnable(BOOL *enable)
7520{
7521 *enable = FALSE;
7522 return RETURN_OK;
7523}
7524
7525//To turn on/off Band steering
7526INT wifi_setBandSteeringEnable(BOOL enable)
7527{
7528 return RETURN_OK;
7529}
7530
7531//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7532//To get Band Steering AP group
7533INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7534{
7535 if (NULL == output_ApGroup)
7536 return RETURN_ERR;
7537
7538 strcpy(output_ApGroup, "1,2");
7539 return RETURN_OK;
7540}
7541
7542//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7543//to set and read the band steering BandUtilizationThreshold parameters
7544INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7545{
7546 return RETURN_ERR;
7547}
7548
7549INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7550{
7551 return RETURN_ERR;
7552}
7553
7554//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7555//to set and read the band steering RSSIThreshold parameters
7556INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7557{
7558 return RETURN_ERR;
7559}
7560
7561INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7562{
7563 return RETURN_ERR;
7564}
7565
7566
7567//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7568//to set and read the band steering physical modulation rate threshold parameters
7569INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7570{
7571 //If chip is not support, return -1
7572 return RETURN_ERR;
7573}
7574
7575INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7576{
7577 //If chip is not support, return -1
7578 return RETURN_ERR;
7579}
7580
7581//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7582//to set and read the inactivity time (in seconds) for steering under overload condition
7583INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7584{
7585 return RETURN_ERR;
7586}
7587
7588INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7589{
7590 return RETURN_ERR;
7591}
7592
7593//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7594//to set and read the inactivity time (in seconds) for steering under Idle condition
7595INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7596{
7597 return RETURN_ERR;
7598}
7599
7600INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7601{
7602 return RETURN_ERR;
7603}
7604
7605//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7606//pClientMAC[64]
7607//pSourceSSIDIndex[64]
7608//pDestSSIDIndex[64]
7609//pSteeringReason[256]
7610INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7611{
7612 //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
7613 *pSteeringTime=time(NULL);
7614 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7615 return RETURN_OK;
7616}
7617
7618INT wifi_ifConfigDown(INT apIndex)
7619{
7620 INT status = RETURN_OK;
7621 char cmd[64];
7622
7623 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7624 printf("%s: %s\n", __func__, cmd);
7625 system(cmd);
7626
7627 return status;
7628}
7629
7630INT wifi_ifConfigUp(INT apIndex)
7631{
7632 char cmd[128];
7633 char buf[1024];
7634
7635 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7636 _syscmd(cmd, buf, sizeof(buf));
7637 return 0;
7638}
7639
7640//>> Deprecated. Replace with wifi_applyRadioSettings
7641INT wifi_pushBridgeInfo(INT apIndex)
7642{
7643 char ip[32];
7644 char subnet[32];
7645 char bridge[32];
7646 int vlanId;
7647 char cmd[128];
7648 char buf[1024];
7649
7650 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7651 wifi_getApVlanID(apIndex,&vlanId);
7652
7653 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7654 _syscmd(cmd,buf, sizeof(buf));
7655
7656 return 0;
7657}
7658
7659INT wifi_pushChannel(INT radioIndex, UINT channel)
7660{
7661 char cmd[128];
7662 char buf[1024];
7663 int apIndex;
7664
7665 apIndex=(radioIndex==0)?0:1;
7666 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7667 _syscmd(cmd,buf, sizeof(buf));
7668
7669 return 0;
7670}
7671
7672INT wifi_pushChannelMode(INT radioIndex)
7673{
7674 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7675 return RETURN_ERR;
7676}
7677
7678INT wifi_pushDefaultValues(INT radioIndex)
7679{
7680 //Apply Comcast specified default radio settings instantly
7681 //AMPDU=1
7682 //AMPDUFrames=32
7683 //AMPDULim=50000
7684 //txqueuelen=1000
7685
7686 return RETURN_ERR;
7687}
7688
7689INT wifi_pushTxChainMask(INT radioIndex)
7690{
7691 //Apply default TxChainMask instantly
7692 return RETURN_ERR;
7693}
7694
7695INT wifi_pushRxChainMask(INT radioIndex)
7696{
7697 //Apply default RxChainMask instantly
7698 return RETURN_ERR;
7699}
7700
7701INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7702{
7703 INT status;
7704
7705 status = wifi_setSSIDName(apIndex,ssid);
7706 wifi_setApEnable(apIndex,FALSE);
7707 wifi_setApEnable(apIndex,TRUE);
7708
7709 return status;
7710}
7711
7712INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7713{
7714 //Apply default Ssid Advertisement instantly
7715 return RETURN_ERR;
7716}
7717
7718INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7719{
7720 INT status = RETURN_ERR;
7721 *output = 0;
7722 return RETURN_ERR;
7723}
7724
7725INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7726{
7727 return RETURN_OK;
7728}
7729
7730INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7731{
7732 return RETURN_OK;
7733}
7734
7735//To-do
7736INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7737{
developereb199ae2022-09-13 14:04:27 +08007738 char output[16]={'\0'};
7739 char config_file[MAX_BUF_SIZE] = {0};
7740
7741 if (!output_string)
7742 return RETURN_ERR;
7743
7744 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7745 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7746
7747 if (strlen(output) == 0)
7748 snprintf(output_string, 64, "Disabled");
7749 else if (strncmp(output, "0", 1) == 0)
7750 snprintf(output_string, 64, "Disabled");
7751 else if (strncmp(output, "1", 1) == 0)
7752 snprintf(output_string, 64, "Optional");
7753 else if (strncmp(output, "2", 1) == 0)
7754 snprintf(output_string, 64, "Required");
7755 else {
7756 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7757 return RETURN_ERR;
7758 }
7759
7760 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007761 return RETURN_OK;
7762}
7763INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7764{
developereb199ae2022-09-13 14:04:27 +08007765 char str[MAX_BUF_SIZE]={'\0'};
7766 char cmd[MAX_CMD_SIZE]={'\0'};
7767 struct params params;
7768 char config_file[MAX_BUF_SIZE] = {0};
7769
7770 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7771 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7772 return RETURN_ERR;
7773
7774 params.name = "ieee80211w";
7775 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7776 params.value = "0";
7777 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7778 params.value = "1";
7779 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7780 params.value = "2";
7781 else{
7782 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7783 return RETURN_ERR;
7784 }
7785 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7786 wifi_hostapdWrite(config_file, &params, 1);
7787 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007788 return RETURN_OK;
7789}
7790INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7791{
7792 char output[16]={'\0'};
7793 char config_file[MAX_BUF_SIZE] = {0};
7794
7795 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7796 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7797 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7798
7799 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7800 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7801
7802 return RETURN_OK;
7803}
7804
7805INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7806{
7807 return RETURN_OK;
7808}
7809
7810INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7811{
7812 return RETURN_OK;
7813}
7814
7815INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7816{
7817 return RETURN_OK;
7818}
7819
7820INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7821{
7822 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7823 char config_file[MAX_BUF_SIZE] = {0};
7824
7825 if (NULL == output)
7826 return RETURN_ERR;
7827 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7828 wifi_hostapdRead(config_file,"hw_mode",output,64);
7829
7830 if(strcmp(output,"b")==0)
7831 sprintf(output, "%s", "1,2,5.5,11");
7832 else if (strcmp(output,"a")==0)
7833 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7834 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7835 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7836
7837 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7838 return RETURN_OK;
7839}
7840
7841INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7842{
7843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7844 char *temp;
7845 char temp_output[128];
7846 char temp_TransmitRates[128];
7847 char config_file[MAX_BUF_SIZE] = {0};
7848
7849 if (NULL == output)
7850 return RETURN_ERR;
7851
7852 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7853 wifi_hostapdRead(config_file,"supported_rates",output,64);
7854
7855 strcpy(temp_TransmitRates,output);
7856 strcpy(temp_output,"");
7857 temp = strtok(temp_TransmitRates," ");
7858 while(temp!=NULL)
7859 {
7860 temp[strlen(temp)-1]=0;
7861 if((temp[0]=='5') && (temp[1]=='\0'))
7862 {
7863 temp="5.5";
7864 }
7865 strcat(temp_output,temp);
7866 temp = strtok(NULL," ");
7867 if(temp!=NULL)
7868 {
7869 strcat(temp_output,",");
7870 }
7871 }
7872 strcpy(output,temp_output);
7873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7874
7875 return RETURN_OK;
7876}
7877
7878INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7879{
7880 return RETURN_OK;
7881}
7882
7883
7884INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7885{
7886 int i=0;
7887 char *temp;
7888 char temp1[128];
7889 char temp_output[128];
7890 char temp_TransmitRates[128];
7891 struct params params={'\0'};
7892 char config_file[MAX_BUF_SIZE] = {0};
7893
7894 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7895 if(NULL == output)
7896 return RETURN_ERR;
7897
7898 strcpy(temp_TransmitRates,output);
7899
7900 for(i=0;i<strlen(temp_TransmitRates);i++)
7901 {
7902 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7903 {
7904 continue;
7905 }
7906 else
7907 {
7908 return RETURN_ERR;
7909 }
7910 }
7911 strcpy(temp_output,"");
7912 temp = strtok(temp_TransmitRates," ");
7913 while(temp!=NULL)
7914 {
7915 strcpy(temp1,temp);
7916 if(wlanIndex==1)
7917 {
7918 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
7919 {
7920 return RETURN_ERR;
7921 }
7922 }
7923
7924 if(strcmp(temp,"5.5")==0)
7925 {
7926 strcpy(temp1,"55");
7927 }
7928 else
7929 {
7930 strcat(temp1,"0");
7931 }
7932 strcat(temp_output,temp1);
7933 temp = strtok(NULL," ");
7934 if(temp!=NULL)
7935 {
7936 strcat(temp_output," ");
7937 }
7938 }
7939 strcpy(output,temp_output);
7940
7941
7942 params.name = "supported_rates";
7943 params.value = output;
7944
7945 wifi_dbg_printf("\n%s:",__func__);
7946 wifi_dbg_printf("params.value=%s\n",params.value);
7947 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7948 wifi_hostapdWrite(config_file,&params,1);
7949 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7950
7951 return RETURN_OK;
7952}
7953
7954
7955static char *sncopy(char *dst, int dst_sz, const char *src)
7956{
7957 if (src && dst && dst_sz > 0) {
7958 strncpy(dst, src, dst_sz);
7959 dst[dst_sz - 1] = '\0';
7960 }
7961 return dst;
7962}
7963
7964static int util_get_sec_chan_offset(int channel, const char* ht_mode)
7965{
7966 if (0 == strcmp(ht_mode, "HT40") ||
7967 0 == strcmp(ht_mode, "HT80") ||
7968 0 == strcmp(ht_mode, "HT160")) {
7969 switch (channel) {
7970 case 1 ... 7:
7971 case 36:
7972 case 44:
7973 case 52:
7974 case 60:
7975 case 100:
7976 case 108:
7977 case 116:
7978 case 124:
7979 case 132:
7980 case 140:
7981 case 149:
7982 case 157:
7983 return 1;
7984 case 8 ... 13:
7985 case 40:
7986 case 48:
7987 case 56:
7988 case 64:
7989 case 104:
7990 case 112:
7991 case 120:
7992 case 128:
7993 case 136:
7994 case 144:
7995 case 153:
7996 case 161:
7997 return -1;
7998 default:
7999 return -EINVAL;
8000 }
8001 }
8002
8003 return -EINVAL;
8004}
8005
8006static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8007{
8008 if (NULL == hw_mode) return;
8009
8010 if (0 == strcmp(hw_mode, "ac"))
8011 sncopy(bw_mode, bw_mode_len, "ht vht");
8012
8013 if (0 == strcmp(hw_mode, "n"))
8014 sncopy(bw_mode, bw_mode_len, "ht");
8015
8016 return;
8017}
8018
8019static int util_chan_to_freq(int chan)
8020{
8021 if (chan == 14)
8022 return 2484;
8023 else if (chan < 14)
8024 return 2407 + chan * 5;
8025 else if (chan >= 182 && chan <= 196)
8026 return 4000 + chan * 5;
8027 else
8028 return 5000 + chan * 5;
8029 return 0;
8030}
8031
8032const int *util_unii_5g_chan2list(int chan, int width)
8033{
8034 static const int lists[] = {
8035 // <width>, <chan1>, <chan2>..., 0,
8036 20, 36, 0,
8037 20, 40, 0,
8038 20, 44, 0,
8039 20, 48, 0,
8040 20, 52, 0,
8041 20, 56, 0,
8042 20, 60, 0,
8043 20, 64, 0,
8044 20, 100, 0,
8045 20, 104, 0,
8046 20, 108, 0,
8047 20, 112, 0,
8048 20, 116, 0,
8049 20, 120, 0,
8050 20, 124, 0,
8051 20, 128, 0,
8052 20, 132, 0,
8053 20, 136, 0,
8054 20, 140, 0,
8055 20, 144, 0,
8056 20, 149, 0,
8057 20, 153, 0,
8058 20, 157, 0,
8059 20, 161, 0,
8060 20, 165, 0,
8061 40, 36, 40, 0,
8062 40, 44, 48, 0,
8063 40, 52, 56, 0,
8064 40, 60, 64, 0,
8065 40, 100, 104, 0,
8066 40, 108, 112, 0,
8067 40, 116, 120, 0,
8068 40, 124, 128, 0,
8069 40, 132, 136, 0,
8070 40, 140, 144, 0,
8071 40, 149, 153, 0,
8072 40, 157, 161, 0,
8073 80, 36, 40, 44, 48, 0,
8074 80, 52, 56, 60, 64, 0,
8075 80, 100, 104, 108, 112, 0,
8076 80, 116, 120, 124, 128, 0,
8077 80, 132, 136, 140, 144, 0,
8078 80, 149, 153, 157, 161, 0,
8079 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8080 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8081 -1 // final delimiter
8082 };
8083 const int *start;
8084 const int *p;
8085
8086 for (p = lists; *p != -1; p++) {
8087 if (*p == width) {
8088 for (start = ++p; *p != 0; p++) {
8089 if (*p == chan)
8090 return start;
8091 }
8092 }
8093 // move to the end of channel list of given width
8094 while (*p != 0) {
8095 p++;
8096 }
8097 }
8098
8099 return NULL;
8100}
8101
8102static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8103{
8104 if (NULL == ht_mode)
8105 return 0;
8106
8107 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8108 const int *chans = util_unii_5g_chan2list(channel, width);
8109 int sum = 0;
8110 int cnt = 0;
8111
8112 if (NULL == chans)
8113 return 0;
8114
8115 while (*chans) {
8116 sum += *chans;
8117 cnt++;
8118 chans++;
8119 }
8120 return sum / cnt;
8121}
8122
8123static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8124{
8125 BOOL onlyG, onlyN, onlyA;
8126 CHAR tmp[64];
8127 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8128 if (ret == RETURN_OK) {
8129 sncopy(hw_mode, hw_mode_size, tmp);
8130 }
8131 return ret;
8132}
8133
8134INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8135{
8136 // Sample commands:
8137 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8138 // hostapd_cli -i wifi0 chan_switch 30 2437
8139 char cmd[MAX_CMD_SIZE] = {0};
8140 char buf[MAX_BUF_SIZE] = {0};
8141 int freq = 0, ret = 0;
8142 char center_freq1_str[32] = ""; // center_freq1=%d
8143 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8144 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8145 char hw_mode[16] = ""; // n|ac
8146 char bw_mode[16] = ""; // ht|ht vht
8147 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8148 int sec_chan_offset;
8149 int width;
8150
8151 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8152
8153 freq = util_chan_to_freq(channel);
8154
8155 // Get radio mode HT20|HT40|HT80 etc.
8156 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
8157 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8158 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8159 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8160 if (sec_chan_offset != -EINVAL)
8161 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
8162
8163
8164 // Provide bandwith if specified
8165 if (channel_width_MHz > 20) {
8166 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8167 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8168 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
8169
8170 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8171 }
8172
8173 int center_chan = 0;
8174 if (channel_width_MHz > 20) {
8175 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8176 if (center_chan > 0) {
8177 int center_freq1 = util_chan_to_freq(center_chan);
8178 if (center_freq1)
8179 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8180 }
8181 }
8182
8183 {
8184 // Only the first AP, other are hanging on the same radio
8185 int apIndex = radioIndex;
8186 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8187 AP_PREFIX, apIndex, csa_beacon_count, freq,
8188 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8189 wifi_dbg_printf("execute: '%s'\n", cmd);
8190 ret = _syscmd(cmd, buf, sizeof(buf));
8191 }
8192
8193 wifi_setRadioChannel(radioIndex, channel);
8194
8195 char *ext_str = "None";
8196 if (sec_chan_offset == 1) ext_str = "Above";
8197 else if (sec_chan_offset == -1) ext_str = "Below";
8198 wifi_setRadioExtChannel(radioIndex, ext_str);
8199
8200 wifi_setRadioCenterChannel(radioIndex, center_chan);
8201
8202 char mhz_str[16];
8203 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8204 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8205
8206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8207
8208 return RETURN_OK;
8209}
8210
8211INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8212{
developer615510b2022-09-27 10:14:35 +08008213 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008214 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008215 char cmd[256]={0};
8216 char buf[128]={0};
8217 char file_name[32] = {0};
8218 char filter_SSID[32] = {0};
8219 char line[256] = {0};
8220 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008221 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008222 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008223 size_t len=0;
8224 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008225 int vht_channel_width = 0;
developer615510b2022-09-27 10:14:35 +08008226 bool get_nosie_ret = false;
8227 bool filter_enable = false;
8228 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008229
developer615510b2022-09-27 10:14:35 +08008230 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008231
developer615510b2022-09-27 10:14:35 +08008232 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8233 f = fopen(file_name, "r");
8234 if (f != NULL) {
8235 fgets(filter_SSID, sizeof(file_name), f);
8236 if (strlen(filter_SSID) != 0)
8237 filter_enable = true;
8238 fclose(f);
8239 }
8240
8241 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8242 _syscmd(cmd, buf, sizeof(buf));
8243 channels_num = strtol(buf, NULL, 10);
8244
8245 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8246 get_nosie_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8247
8248 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8249 // 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);
8250 fprintf(stderr, "cmd: %s\n", cmd);
8251 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008252 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8253 return RETURN_ERR;
8254 }
developer615510b2022-09-27 10:14:35 +08008255 ret = fgets(line, sizeof(line), f);
8256 while (ret != NULL) {
8257 if(strstr(line, "BSS") != NULL) { // new neighbor info
8258 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8259 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8260 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8261
8262 if (!filter_BSS) {
8263 index++;
8264 wifi_neighbor_ap2_t *tmp;
8265 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8266 if (tmp == NULL) { // no more memory to use
8267 index--;
8268 wifi_dbg_printf("%s: realloc failed\n", __func__);
8269 break;
8270 }
8271 scan_array = tmp;
8272 }
8273 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008274
developer615510b2022-09-27 10:14:35 +08008275 filter_BSS = false;
8276 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8277 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8278 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8279 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8280 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008281 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008282 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008283
developer615510b2022-09-27 10:14:35 +08008284 if (freq >= 2412 && freq <= 2484) {
8285 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8286 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8287 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8288 }
8289 else if (freq >= 5160 && freq <= 5805) {
8290 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8291 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8292 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8293 }
developer06a01d92022-09-07 16:32:39 +08008294
developer615510b2022-09-27 10:14:35 +08008295 scan_array[index].ap_Noise = 0;
8296 if (get_nosie_ret) {
8297 for (int i = 0; i < channels_num; i++) {
8298 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8299 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8300 break;
8301 }
8302 }
developer06a01d92022-09-07 16:32:39 +08008303 }
developer615510b2022-09-27 10:14:35 +08008304 } else if (strstr(line, "beacon interval") != NULL) {
8305 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8306 } else if (strstr(line, "signal") != NULL) {
8307 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8308 } else if (strstr(line,"SSID") != NULL) {
8309 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8310 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8311 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008312 }
developer615510b2022-09-27 10:14:35 +08008313 } else if (strstr(line, "Supported rates") != NULL) {
8314 char SRate[80] = {0}, *tmp = NULL;
8315 memset(buf, 0, sizeof(buf));
8316 strcpy(SRate, line);
8317 tmp = strtok(SRate, ":");
8318 tmp = strtok(NULL, ":");
8319 strcpy(buf, tmp);
8320 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008321
developer615510b2022-09-27 10:14:35 +08008322 tmp = strtok(buf, " \n");
8323 while (tmp != NULL) {
8324 strcat(SRate, tmp);
8325 if (SRate[strlen(SRate) - 1] == '*') {
8326 SRate[strlen(SRate) - 1] = '\0';
8327 }
8328 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008329
developer615510b2022-09-27 10:14:35 +08008330 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008331 }
developer615510b2022-09-27 10:14:35 +08008332 SRate[strlen(SRate) - 1] = '\0';
8333 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8334 } else if (strstr(line, "DTIM") != NULL) {
8335 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8336 } else if (strstr(line, "VHT capabilities") != NULL) {
8337 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8338 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8339 } else if (strstr(line, "HT capabilities") != NULL) {
8340 strcat(scan_array[index].ap_SupportedStandards, ",n");
8341 strcpy(scan_array[index].ap_OperatingStandards, "n");
8342 } else if (strstr(line, "VHT operation") != NULL) {
8343 ret = fgets(line, sizeof(line), f);
8344 sscanf(line," * channel width: %d", &vht_channel_width);
8345 if(vht_channel_width == 1) {
8346 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8347 } else {
8348 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8349 }
8350 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8351 continue;
8352 } else if (strstr(line, "HT operation") != NULL) {
8353 ret = fgets(line, sizeof(line), f);
8354 sscanf(line," * secondary channel offset: %s", &buf);
8355 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008356 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008357 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 +08008358 }
developer615510b2022-09-27 10:14:35 +08008359 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008360 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008361 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8362 } else {
8363 //20Mhz
8364 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 +08008365 }
developer615510b2022-09-27 10:14:35 +08008366 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008367 continue;
developer615510b2022-09-27 10:14:35 +08008368 } else if (strstr(line, "HE capabilities") != NULL) {
8369 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8370 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8371 ret = fgets(line, sizeof(line), f);
8372 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8373 if (strstr(line, "HE40/2.4GHz") != NULL)
8374 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8375 else
8376 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8377 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8378 if (strstr(line, "HE80/5GHz") != NULL) {
8379 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8380 ret = fgets(line, sizeof(line), f);
8381 } else
8382 continue;
8383 if (strstr(line, "HE160/5GHz") != NULL)
8384 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008385 }
developer615510b2022-09-27 10:14:35 +08008386 continue;
8387 } else if (strstr(line, "WPA") != NULL) {
8388 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8389 } else if (strstr(line, "RSN") != NULL) {
8390 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8391 } else if (strstr(line, "Group cipher") != NULL) {
8392 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8393 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8394 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008395 }
developer06a01d92022-09-07 16:32:39 +08008396 }
developer615510b2022-09-27 10:14:35 +08008397 ret = fgets(line, sizeof(line), f);
8398 }
8399
8400 if (!filter_BSS) {
8401 *output_array_size = index + 1;
8402 } else {
8403 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8404 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008405 }
developer06a01d92022-09-07 16:32:39 +08008406 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008407 pclose(f);
developer615510b2022-09-27 10:14:35 +08008408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008409 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008410}
developer615510b2022-09-27 10:14:35 +08008411
developer06a01d92022-09-07 16:32:39 +08008412INT wifi_getApAssociatedDeviceStats(
8413 INT apIndex,
8414 mac_address_t *clientMacAddress,
8415 wifi_associated_dev_stats_t *associated_dev_stats,
8416 u64 *handle)
8417{
8418 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8419 char interface_name[50] = {0};
8420 char cmd[1024] = {0};
8421 char mac_str[18] = {0};
8422 char *key = NULL;
8423 char *val = NULL;
8424 FILE *f = NULL;
8425 char *line = NULL;
8426 size_t len = 0;
8427 ssize_t read = 0;
8428
8429 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8430 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8431 return RETURN_ERR;
8432 }
8433
8434 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8435 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8436 if((f = popen(cmd, "r")) == NULL) {
8437 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8438 return RETURN_ERR;
8439 }
8440
8441 while ((read = getline(&line, &len, f)) != -1) {
8442 key = strtok(line,":");
8443 val = strtok(NULL,":");
8444
8445 if(!strncmp(key,"rx bytes",8))
8446 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8447 if(!strncmp(key,"tx bytes",8))
8448 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8449 if(!strncmp(key,"rx packets",10))
8450 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8451 if(!strncmp(key,"tx packets",10))
8452 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8453 if(!strncmp(key,"tx retries",10))
8454 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8455 if(!strncmp(key,"tx failed",9))
8456 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8457 if(!strncmp(key,"rx drop misc",13))
8458 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8459 if(!strncmp(key,"rx bitrate",10)) {
8460 val = strtok(val, " ");
8461 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8462 }
8463 if(!strncmp(key,"tx bitrate",10)) {
8464 val = strtok(val, " ");
8465 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8466 }
8467 }
8468 free(line);
8469 pclose(f);
8470 return RETURN_OK;
8471}
8472
8473INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8474{
8475 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8476
8477 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8478 if (NULL == output_string)
8479 return RETURN_ERR;
8480
8481 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8482 _syscmd(cmd, buf, sizeof(buf));
8483
8484 //size of SSID name restricted to value less than 32 bytes
8485 snprintf(output_string, 32, "%s", buf);
8486 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8487
8488 return RETURN_OK;
8489}
8490
8491INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8492{
8493 //char cmd[MAX_CMD_SIZE] = {0};
8494 char config_file[MAX_BUF_SIZE] = {0};
8495 char buf[32] = {0};
8496
8497 if (!output_filterMode)
8498 return RETURN_ERR;
8499
8500 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8501 //_syscmd(cmd, buf, sizeof(buf));
8502 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8503 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008504 if(strlen(buf) == 0) {
8505 *output_filterMode = 0;
8506 }
8507 else {
8508 int macaddr_acl_mode = strtol(buf, NULL, 10);
8509 if (macaddr_acl_mode == 1) {
8510 *output_filterMode = 1;
8511 } else if (macaddr_acl_mode == 0) {
8512 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8513 if (strlen(buf) == 0) {
8514 *output_filterMode = 0;
8515 } else {
8516 *output_filterMode = 2;
8517 }
8518 } else {
8519 return RETURN_ERR;
8520 }
8521 }
developer06a01d92022-09-07 16:32:39 +08008522
8523 return RETURN_OK;
8524}
8525
8526INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8527{
8528 FILE *fp = NULL;
8529 char str[MAX_BUF_SIZE] = {0};
8530 int wificlientindex = 0 ;
8531 int count = 0;
8532 int signalstrength = 0;
8533 int arr[MACADDRESS_SIZE] = {0};
8534 unsigned char mac[MACADDRESS_SIZE] = {0};
8535 UINT wifi_count = 0;
8536 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8537 char pipeCmd[MAX_CMD_SIZE] = {0};
8538
8539 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8540 *output_array_size = 0;
8541 *associated_dev_array = NULL;
8542 char interface_name[50] = {0};
8543
8544 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8545 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8546 return RETURN_ERR;
8547 }
8548
8549 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8550 fp = popen(pipeCmd, "r");
8551 if (fp == NULL)
8552 {
8553 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8554 return RETURN_ERR;
8555 }
8556
8557 /* Read the output a line at a time - output it. */
8558 fgets(str, sizeof(str)-1, fp);
8559 wifi_count = (unsigned int) atoi ( str );
8560 *output_array_size = wifi_count;
8561 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8562 pclose(fp);
8563
8564 if(wifi_count == 0)
8565 {
8566 return RETURN_OK;
8567 }
8568 else
8569 {
8570 wifi_associated_dev2_t* temp = NULL;
8571 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8572 *associated_dev_array = temp;
8573 if(temp == NULL)
8574 {
8575 printf("Error Statement. Insufficient memory \n");
8576 return RETURN_ERR;
8577 }
8578
8579 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8580 system(pipeCmd);
8581
8582 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8583 if(fp == NULL)
8584 {
8585 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8586 return RETURN_ERR;
8587 }
8588 fclose(fp);
8589
8590 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8591 fp = popen(pipeCmd, "r");
8592 if(fp)
8593 {
8594 for(count =0 ; count < wifi_count; count++)
8595 {
8596 fgets(str, MAX_BUF_SIZE, fp);
8597 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8598 {
8599 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8600 {
8601 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8602
8603 }
8604 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8605 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]);
8606 }
8607 temp[count].cli_AuthenticationState = 1; //TODO
8608 temp[count].cli_Active = 1; //TODO
8609 }
8610 pclose(fp);
8611 }
8612
8613 //Updating RSSI per client
8614 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8615 fp = popen(pipeCmd, "r");
8616 if(fp)
8617 {
8618 pclose(fp);
8619 }
8620 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8621 if(fp)
8622 {
8623 for(count =0 ; count < wifi_count ;count++)
8624 {
8625 fgets(str, MAX_BUF_SIZE, fp);
8626 signalstrength = atoi(str);
8627 temp[count].cli_RSSI = signalstrength;
8628 }
8629 pclose(fp);
8630 }
8631
8632
8633 //LastDataDownlinkRate
8634 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8635 fp = popen(pipeCmd, "r");
8636 if (fp)
8637 {
8638 pclose(fp);
8639 }
8640 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8641 if (fp)
8642 {
8643 for (count = 0; count < wifi_count; count++)
8644 {
8645 fgets(str, MAX_BUF_SIZE, fp);
8646 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8647 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8648 }
8649 pclose(fp);
8650 }
8651
8652 //LastDataUplinkRate
8653 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8654 fp = popen(pipeCmd, "r");
8655 if (fp)
8656 {
8657 pclose(fp);
8658 }
8659 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8660 if (fp)
8661 {
8662 for (count = 0; count < wifi_count; count++)
8663 {
8664 fgets(str, MAX_BUF_SIZE, fp);
8665 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8666 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8667 }
8668 pclose(fp);
8669 }
8670 }
8671 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8672 return RETURN_OK;
8673
8674}
8675
8676INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8677{
8678#if 0
8679 /*char buf[1024] = {0};
8680 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8681 _syscmd(cmd, buf, sizeof(buf));*/
8682
8683 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8684 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8685 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8686 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8687
8688 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.
8689 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].
8690 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].
8691 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].
8692 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8693 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8694
8695 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8696 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8697 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8698 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.
8699 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.
8700 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.
8701 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.
8702 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.
8703 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.
8704 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.
8705 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8706#endif
8707
8708 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008709 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008710 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008711 char pipeCmd[128] = {0};
8712 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008713 wifi_ssidTrafficStats2_t *out = output_struct;
8714
developerce736392022-09-13 15:24:34 +08008715 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008716 if (!output_struct)
8717 return RETURN_ERR;
8718
developerce736392022-09-13 15:24:34 +08008719 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8720 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8721 GetInterfaceName(interface_name, HConf_file);
8722 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008723
developer06a01d92022-09-07 16:32:39 +08008724 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008725 if (fp == NULL) {
8726 fprintf(stderr, "%s: popen failed\n", __func__);
8727 return RETURN_ERR;
8728 }
8729 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008730
developerce736392022-09-13 15:24:34 +08008731 if (strlen(str) == 0) // interface not exist
8732 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008733
developerce736392022-09-13 15:24:34 +08008734 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8735 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008736 pclose(fp);
8737
developerce736392022-09-13 15:24:34 +08008738 memset(str, 0, sizeof(str));
8739 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008740 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008741 if (fp == NULL) {
8742 fprintf(stderr, "%s: popen failed\n", __func__);
8743 return RETURN_ERR;
8744 }
8745 fgets(str, sizeof(str), fp);
8746
8747 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8748 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008749 pclose(fp);
developerce736392022-09-13 15:24:34 +08008750
8751 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8752 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8753
8754 // Not supported
8755 output_struct->ssid_RetransCount = 0;
8756 output_struct->ssid_FailedRetransCount = 0;
8757 output_struct->ssid_RetryCount = 0;
8758 output_struct->ssid_MultipleRetryCount = 0;
8759 output_struct->ssid_ACKFailureCount = 0;
8760 output_struct->ssid_AggregatedPacketCount = 0;
8761
developer06a01d92022-09-07 16:32:39 +08008762 return RETURN_OK;
8763}
8764
8765//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).
8766INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8767{
8768 char output_val[16]={'\0'};
8769 char config_file[MAX_BUF_SIZE] = {0};
8770
8771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8772 if (!output)
8773 return RETURN_ERR;
8774 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8775 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8776
8777 if( strcmp(output_val,"1") == 0 )
8778 *output = TRUE;
8779 else
8780 *output = FALSE;
8781 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8782
8783 return RETURN_OK;
8784}
8785
8786INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8787{
8788 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8789 char str[MAX_BUF_SIZE]={'\0'};
8790 char string[MAX_BUF_SIZE]={'\0'};
8791 char cmd[MAX_CMD_SIZE]={'\0'};
8792 char *ch;
8793 char config_file[MAX_BUF_SIZE] = {0};
8794 struct params params;
8795
8796 if(enable == TRUE)
8797 strcpy(string,"1");
8798 else
8799 strcpy(string,"0");
8800
8801 params.name = "ap_isolate";
8802 params.value = string;
8803
8804 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8805 wifi_hostapdWrite(config_file,&params,1);
8806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8807
8808 return RETURN_OK;
8809}
8810
8811INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8812{
8813 if (NULL == output_dBm)
8814 return RETURN_ERR;
8815
8816 *output_dBm = 0;
8817 return RETURN_OK;
8818}
8819
8820INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8821{
8822 return RETURN_OK;
8823}
8824INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8825{
8826 return RETURN_OK;
8827}
8828INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8829{
8830 return RETURN_OK;
8831}
8832INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8833{
8834 return RETURN_OK;
8835}
8836INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8837{
8838 return RETURN_OK;
8839}
8840INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8841{
8842 char config_file[MAX_BUF_SIZE] = {0};
8843 struct params list;
8844
8845 list.name = "bss_transition";
8846 list.value = activate?"1":"0";
8847 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8848 wifi_hostapdWrite(config_file, &list, 1);
8849
8850 return RETURN_OK;
8851}
8852wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8853
8854void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8855{
8856 return;
8857}
8858
8859INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8860{
8861 // TODO Implement me!
8862 return RETURN_OK;
8863}
8864
8865INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8866{
developera3c68b92022-09-13 15:27:29 +08008867 char file_name[128] = {0};
8868 char buf[128] = {0};
8869 FILE *f = NULL;
8870
8871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8872
8873 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8874 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8875 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8876 f = fopen(file_name, "w");
8877 if (f == NULL)
8878 return RETURN_ERR;
8879 // For mode == 0 is to disable filter, just don't write to the file.
8880 if (mode)
8881 fprintf(f, "%s", essid);
8882
8883 fclose(f);
8884 }
8885 } else { // special case, need to set AP's SSID as filter for each radio.
8886 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8887 f = fopen(file_name, "w");
8888 if (f == NULL)
8889 return RETURN_ERR;
8890
8891 // For mode == 0 is to disable filter, just don't write to the file.
8892 if (mode)
8893 fprintf(f, "%s", essid);
8894
8895 fclose(f);
8896 }
8897
8898 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008899 return RETURN_OK;
8900}
8901
8902INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
8903{
8904 // TODO Implement me!
8905 //Apply wifi_pushRadioChannel() instantly
8906 return RETURN_ERR;
8907}
8908
8909INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
8910{
8911 // TODO Implement me!
8912 return RETURN_OK;
8913}
8914
8915#ifdef HAL_NETLINK_IMPL
8916static int tidStats_callback(struct nl_msg *msg, void *arg) {
8917 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8918 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8919 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8920 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
8921 int rem , tid_index = 0;
8922
8923 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
8924 wifi_associated_dev_tid_entry_t *stats_entry;
8925
8926 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
8927 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
8928 };
8929 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
8930 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
8931 };
8932
8933 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8934 genlmsg_attrlen(gnlh, 0), NULL);
8935
8936
8937 if (!tb[NL80211_ATTR_STA_INFO]) {
8938 fprintf(stderr, "station stats missing!\n");
8939 return NL_SKIP;
8940 }
8941
8942 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
8943 tb[NL80211_ATTR_STA_INFO],
8944 stats_policy)) {
8945 fprintf(stderr, "failed to parse nested attributes!\n");
8946 return NL_SKIP;
8947 }
8948
8949 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
8950 {
8951 stats_entry = &out->tid_array[tid_index];
8952
8953 stats_entry->tid = tid_index;
8954 stats_entry->ac = _tid_ac_index_get[tid_index];
8955
8956 if(sinfo[NL80211_STA_INFO_TID_STATS])
8957 {
8958 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
8959 printf("failed to parse nested stats attributes!");
8960 return NL_SKIP;
8961 }
8962 }
8963 if(stats_info[NL80211_TID_STATS_TX_MSDU])
8964 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
8965
8966 if(tid_index < (PS_MAX_TID - 1))
8967 tid_index++;
8968 }
8969 //ToDo: sum_time_ms, ewma_time_ms
8970 return NL_SKIP;
8971}
8972#endif
8973
8974INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
8975{
8976#ifdef HAL_NETLINK_IMPL
8977 Netlink nl;
8978 char if_name[10];
8979
8980 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8981
8982 nl.id = initSock80211(&nl);
8983
8984 if (nl.id < 0) {
8985 fprintf(stderr, "Error initializing netlink \n");
8986 return -1;
8987 }
8988
8989 struct nl_msg* msg = nlmsg_alloc();
8990
8991 if (!msg) {
8992 fprintf(stderr, "Failed to allocate netlink message.\n");
8993 nlfree(&nl);
8994 return -2;
8995 }
8996
8997 genlmsg_put(msg,
8998 NL_AUTO_PORT,
8999 NL_AUTO_SEQ,
9000 nl.id,
9001 0,
9002 0,
9003 NL80211_CMD_GET_STATION,
9004 0);
9005
9006 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9007 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9008 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9009 nl_send_auto(nl.socket, msg);
9010 nl_recvmsgs(nl.socket, nl.cb);
9011 nlmsg_free(msg);
9012 nlfree(&nl);
9013 return RETURN_OK;
9014#else
9015//iw implementation
9016#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9017#define TOTAL_MAX_LINES 50
9018
9019 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9020 char if_name[10];
9021 FILE *fp=NULL;
9022 char pipeCmd[1024]= {'\0'};
9023 int lines,tid_index=0;
9024 char mac_addr[20] = {'\0'};
9025
9026 wifi_associated_dev_tid_entry_t *stats_entry;
9027
9028 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9029 strcpy(mac_addr,clientMacAddress);
9030
9031 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9032 fp= popen(pipeCmd,"r");
9033 if(fp == NULL)
9034 {
9035 perror("popen for station dump failed\n");
9036 return RETURN_ERR;
9037 }
9038 pclose(fp);
9039
9040 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9041 fp=popen(pipeCmd,"r");
9042 if(fp == NULL)
9043 {
9044 perror("popen for grep station failed\n");
9045 return RETURN_ERR;
9046 }
9047 else if(fgets(buf,sizeof(buf),fp) != NULL)
9048 lines=atoi(buf);
9049 else
9050 {
9051 pclose(fp);
9052 fprintf(stderr,"No devices are connected \n");
9053 return RETURN_ERR;
9054 }
9055 pclose(fp);
9056
9057 if(lines == 1)
9058 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9059
9060 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9061 {
9062 stats_entry = &tid_stats->tid_array[tid_index];
9063 stats_entry->tid = tid_index;
9064
9065 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);
9066
9067 fp=popen(pipeCmd,"r");
9068 if(fp ==NULL)
9069 {
9070 perror("Failed to read from tid file \n");
9071 return RETURN_ERR;
9072 }
9073 else if(fgets(buf,sizeof(buf),fp) != NULL)
9074 stats_entry->num_msdus = atol(buf);
9075
9076 pclose(fp);
9077 stats_entry->ac = _tid_ac_index_get[tid_index];
9078// TODO:
9079// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9080// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9081 }
9082 return RETURN_OK;
9083#endif
9084}
9085
9086
9087INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9088{
developer615510b2022-09-27 10:14:35 +08009089 char cmd[128]={0};
9090 char buf[128]={0};
9091 int freq = 0;
9092
9093 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9094
9095 // full mode is used to scan all channels.
9096 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9097 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9098 ieee80211_channel_to_frequency(chan_list[0], &freq);
9099
9100 if (freq)
9101 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9102 else
9103 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9104
9105 _syscmd(cmd, buf, sizeof(buf));
9106 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9107
developer06a01d92022-09-07 16:32:39 +08009108 return RETURN_OK;
9109}
9110
9111
9112INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9113{
9114 // TODO Implement me!
9115 return RETURN_ERR;
9116}
9117
9118INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9119{
9120 // TODO Implement me!
9121 return RETURN_ERR;
9122}
9123
9124INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9125{
9126 // TODO Implement me!
9127 return RETURN_ERR;
9128}
9129
9130INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9131{
9132 // TODO Implement me!
9133 return RETURN_ERR;
9134}
9135
9136INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9137{
9138 // TODO Implement me!
9139 return RETURN_ERR;
9140}
9141
9142INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9143{
9144 // TODO Implement me!
9145 return RETURN_ERR;
9146}
9147
9148INT wifi_steering_eventUnregister(void)
9149{
9150 // TODO Implement me!
9151 return RETURN_ERR;
9152}
9153
9154INT wifi_delApAclDevices(INT apIndex)
9155{
9156#if 0
9157 char cmd[MAX_BUF_SIZE] = {0};
9158 char buf[MAX_BUF_SIZE] = {0};
9159
9160 /* Not reset proof solution */
9161 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9162 if(_syscmd(cmd,buf,sizeof(buf)))
9163 return RETURN_ERR;
9164#endif
developere6aafda2022-09-13 14:59:28 +08009165 char cmd[MAX_CMD_SIZE]={0};
9166 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009167
developere6aafda2022-09-13 14:59:28 +08009168 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9169 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9170 if(_syscmd(cmd, buf, sizeof(buf)))
9171 return RETURN_ERR;
9172 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009173
9174 return RETURN_OK;
9175}
9176
9177#ifdef HAL_NETLINK_IMPL
9178static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9179 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9180 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9181 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9182 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9183 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9184 char mac_addr[20],dev[20];
9185
9186 nla_parse(tb,
9187 NL80211_ATTR_MAX,
9188 genlmsg_attrdata(gnlh, 0),
9189 genlmsg_attrlen(gnlh, 0),
9190 NULL);
9191
9192 if(!tb[NL80211_ATTR_STA_INFO]) {
9193 fprintf(stderr, "sta stats missing!\n");
9194 return NL_SKIP;
9195 }
9196
9197 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9198 fprintf(stderr, "failed to parse nested attributes!\n");
9199 return NL_SKIP;
9200 }
9201 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9202
9203 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9204
9205 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9206 fprintf(stderr, "failed to parse nested rate attributes!");
9207 return NL_SKIP;
9208 }
9209
9210 if(sinfo[NL80211_STA_INFO_TID_STATS])
9211 {
9212 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9213 printf("failed to parse nested stats attributes!");
9214 return NL_SKIP;
9215 }
9216 }
9217
9218 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9219 {
9220 printf("Type is VHT\n");
9221 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9222 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9223
9224 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9225 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9226 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9227 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9228 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9229 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9230 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9231 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9232 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9233 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9234 }
9235 else
9236 {
9237 printf(" OFDM or CCK \n");
9238 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9239 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9240 }
9241
9242 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9243 if(rinfo[NL80211_RATE_INFO_MCS])
9244 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9245 }
9246 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9247 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9248 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9249 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9250
9251 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9252 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9253
9254 if (sinfo[NL80211_STA_INFO_SIGNAL])
9255 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9256 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9257 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9258 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9259 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9260 //rssi_array need to be filled
9261 return NL_SKIP;
9262}
9263#endif
9264
9265INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9266{
9267#ifdef HAL_NETLINK_IMPL
9268 Netlink nl;
9269 char if_name[10];
9270
9271 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9272
9273 if (*output_array_size <= 0)
9274 return RETURN_OK;
9275
9276 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9277 nl.id = initSock80211(&nl);
9278
9279 if (nl.id < 0) {
9280 fprintf(stderr, "Error initializing netlink \n");
9281 return 0;
9282 }
9283
9284 struct nl_msg* msg = nlmsg_alloc();
9285
9286 if (!msg) {
9287 fprintf(stderr, "Failed to allocate netlink message.\n");
9288 nlfree(&nl);
9289 return 0;
9290 }
9291
9292 genlmsg_put(msg,
9293 NL_AUTO_PORT,
9294 NL_AUTO_SEQ,
9295 nl.id,
9296 0,
9297 0,
9298 NL80211_CMD_GET_STATION,
9299 0);
9300
9301 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9302 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9303 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9304 nl_send_auto(nl.socket, msg);
9305 nl_recvmsgs(nl.socket, nl.cb);
9306 nlmsg_free(msg);
9307 nlfree(&nl);
9308 return RETURN_OK;
9309#else
9310 //TODO Implement me
9311 return RETURN_OK;
9312#endif
9313}
9314
9315#ifdef HAL_NETLINK_IMPL
9316static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9317 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9318 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9319 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9320 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9321 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9322 char mac_addr[20],dev[20];
9323
9324 nla_parse(tb,
9325 NL80211_ATTR_MAX,
9326 genlmsg_attrdata(gnlh, 0),
9327 genlmsg_attrlen(gnlh, 0),
9328 NULL);
9329
9330 if(!tb[NL80211_ATTR_STA_INFO]) {
9331 fprintf(stderr, "sta stats missing!\n");
9332 return NL_SKIP;
9333 }
9334
9335 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9336 fprintf(stderr, "failed to parse nested attributes!\n");
9337 return NL_SKIP;
9338 }
9339
9340 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9341
9342 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9343
9344 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9345 fprintf(stderr, "failed to parse nested rate attributes!");
9346 return NL_SKIP;
9347 }
9348
9349 if(sinfo[NL80211_STA_INFO_TID_STATS])
9350 {
9351 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9352 printf("failed to parse nested stats attributes!");
9353 return NL_SKIP;
9354 }
9355 }
9356 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9357 {
9358 printf("Type is VHT\n");
9359 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9360 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9361
9362 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9363 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9364 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9365 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9366 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9367 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9368 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9369 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9370 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9371 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9372 }
9373 else
9374 {
9375 printf(" OFDM or CCK \n");
9376 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9377 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9378 }
9379
9380 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9381 if(rinfo[NL80211_RATE_INFO_MCS])
9382 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9383 }
9384
9385 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9386 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9387 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9388 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9389
9390 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9391 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9392 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9393
9394 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9395 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9396
9397 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9398 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9399
9400 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9401 ((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]);
9402
9403 return NL_SKIP;
9404}
9405#endif
9406
9407INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9408{
9409#ifdef HAL_NETLINK_IMPL
9410 Netlink nl;
9411 char if_name[10];
9412
9413 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9414
9415 if (*output_array_size <= 0)
9416 return RETURN_OK;
9417
9418 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9419
9420 nl.id = initSock80211(&nl);
9421
9422 if(nl.id < 0) {
9423 fprintf(stderr, "Error initializing netlink \n");
9424 return 0;
9425 }
9426
9427 struct nl_msg* msg = nlmsg_alloc();
9428
9429 if(!msg) {
9430 fprintf(stderr, "Failed to allocate netlink message.\n");
9431 nlfree(&nl);
9432 return 0;
9433 }
9434
9435 genlmsg_put(msg,
9436 NL_AUTO_PORT,
9437 NL_AUTO_SEQ,
9438 nl.id,
9439 0,
9440 0,
9441 NL80211_CMD_GET_STATION,
9442 0);
9443
9444 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9445 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9446 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9447 nl_send_auto(nl.socket, msg);
9448 nl_recvmsgs(nl.socket, nl.cb);
9449 nlmsg_free(msg);
9450 nlfree(&nl);
9451 return RETURN_OK;
9452#else
9453 //TODO Implement me
9454 return RETURN_OK;
9455#endif
9456}
9457
9458INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9459{
9460 // TODO Implement me!
9461 char buf[MAX_BUF_SIZE] = {0};
9462 char config_file[MAX_BUF_SIZE] = {0};
9463
9464 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9465 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9466 *activate = (strncmp("1",buf,1) == 0);
9467
9468 return RETURN_OK;
9469}
9470
9471INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9472{
9473 char config_file[MAX_BUF_SIZE] = {0};
9474 struct params list;
9475
9476 list.name = "rrm_neighbor_report";
9477 list.value = activate?"1":"0";
9478 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9479 wifi_hostapdWrite(config_file, &list, 1);
9480
9481 return RETURN_OK;
9482}
9483
9484INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9485{
9486 char buf[32] = {0};
9487 char config_file[MAX_BUF_SIZE] = {0};
9488
9489 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9490 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9491 *activate = (strncmp("1",buf,1) == 0);
9492
9493 return RETURN_OK;
9494}
9495#undef HAL_NETLINK_IMPL
9496#ifdef HAL_NETLINK_IMPL
9497static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9498 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9499 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9500 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9501 char dev[20];
9502 int freq =0 ;
9503 static int i=0;
9504
9505 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9506
9507 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9508 };
9509
9510 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9511
9512 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9513
9514 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9515 fprintf(stderr, "survey data missing!\n");
9516 return NL_SKIP;
9517 }
9518
9519 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9520 {
9521 fprintf(stderr, "failed to parse nested attributes!\n");
9522 return NL_SKIP;
9523 }
9524
9525
9526 if(out[0].array_size == 1 )
9527 {
9528 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9529 {
9530 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9531 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9532 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9533
9534 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9535 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9536 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9537 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9538 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9539 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9540 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9541 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9542 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9543 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9544 if (sinfo[NL80211_SURVEY_INFO_TIME])
9545 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9546 return NL_STOP;
9547 }
9548 }
9549 else
9550 {
9551 if ( i <= out[0].array_size )
9552 {
9553 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9554 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9555 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9556
9557 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9558 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9559 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9560 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9561 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9562 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9563 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9564 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9565 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9566 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9567 if (sinfo[NL80211_SURVEY_INFO_TIME])
9568 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9569 }
9570 }
9571
9572 i++;
9573 return NL_SKIP;
9574}
9575#endif
9576
9577static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9578{
9579 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9580 FILE *fp;
9581
9582 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9583 {
9584 printf("Creating Frequency-Channel Map\n");
9585 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9586 }
9587 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9588 if((fp = popen(command, "r")))
9589 {
9590 fgets(output, sizeof(output), fp);
9591 *freqMHz = atoi(output);
9592 fclose(fp);
9593 }
9594
9595 return 0;
9596}
9597
9598static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9599{
9600 int freqMHz = -1;
9601 char cmd[MAX_CMD_SIZE] = {'\0'};
9602
9603 ieee80211_channel_to_frequency(channel, &freqMHz);
9604 if (freqMHz == -1) {
9605 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9606 return -1;
9607 }
9608
9609 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9610 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9611 radioIndex, freqMHz);
9612 return -1;
9613 }
9614
9615 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9616 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9617 return -1;
9618 }
9619
9620 return 0;
9621}
9622
9623static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9624{
9625 const char *ptr = buf;
9626 char *key = NULL;
9627 char *val = NULL;
9628 char line[256] = { '\0' };
9629
9630 while (ptr = get_line_from_str_buf(ptr, line)) {
9631 if (strstr(line, "Frequency")) continue;
9632
9633 key = strtok(line, ":");
9634 val = strtok(NULL, " ");
9635 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9636
9637 if (!strcmp(key, "noise")) {
9638 sscanf(val, "%d", &stats->ch_noise);
9639 if (stats->ch_noise == 0) {
9640 // Workaround for missing noise information.
9641 // Assume -95 for 2.4G and -103 for 5G
9642 if (radioIndex == 0) stats->ch_noise = -95;
9643 if (radioIndex == 1) stats->ch_noise = -103;
9644 }
9645 }
9646 else if (!strcmp(key, "channel active time")) {
9647 sscanf(val, "%llu", &stats->ch_utilization_total);
9648 }
9649 else if (!strcmp(key, "channel busy time")) {
9650 sscanf(val, "%llu", &stats->ch_utilization_busy);
9651 }
9652 else if (!strcmp(key, "channel receive time")) {
9653 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9654 }
9655 else if (!strcmp(key, "channel transmit time")) {
9656 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9657 }
9658 };
9659
9660 return 0;
9661}
9662
9663INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9664{
9665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9666#ifdef HAL_NETLINK_IMPL
9667 Netlink nl;
9668 wifi_channelStats_t_loc local[array_size];
9669 char if_name[10];
9670
9671 local[0].array_size = array_size;
9672
9673 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9674
9675 nl.id = initSock80211(&nl);
9676
9677 if (nl.id < 0) {
9678 fprintf(stderr, "Error initializing netlink \n");
9679 return -1;
9680 }
9681
9682 struct nl_msg* msg = nlmsg_alloc();
9683
9684 if (!msg) {
9685 fprintf(stderr, "Failed to allocate netlink message.\n");
9686 nlfree(&nl);
9687 return -2;
9688 }
9689
9690 genlmsg_put(msg,
9691 NL_AUTO_PORT,
9692 NL_AUTO_SEQ,
9693 nl.id,
9694 0,
9695 NLM_F_DUMP,
9696 NL80211_CMD_GET_SURVEY,
9697 0);
9698
9699 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9700 nl_send_auto(nl.socket, msg);
9701 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9702 nl_recvmsgs(nl.socket, nl.cb);
9703 nlmsg_free(msg);
9704 nlfree(&nl);
9705 //Copying the Values
9706 for(int i=0;i<array_size;i++)
9707 {
9708 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9709 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9710 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9711 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9712 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9713 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9714 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9715 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9716 }
9717#else
9718 ULONG channel = 0;
9719 int i;
9720 int number_of_channels = array_size;
9721 char buf[512];
9722 INT ret;
9723 wifi_channelStats_t tmp_stats;
9724
9725 if (number_of_channels == 0) {
9726 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9727 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9728 return RETURN_ERR;
9729 }
9730 number_of_channels = 1;
9731 input_output_channelStats_array[0].ch_number = channel;
9732 }
9733
9734 for (i = 0; i < number_of_channels; i++) {
9735
9736 input_output_channelStats_array[i].ch_noise = 0;
9737 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9738 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9739 input_output_channelStats_array[i].ch_utilization_busy = 0;
9740 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9741 input_output_channelStats_array[i].ch_utilization_total = 0;
9742
9743 memset(buf, 0, sizeof(buf));
9744 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9745 return RETURN_ERR;
9746 }
9747 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9748 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9749 return RETURN_ERR;
9750 }
9751
9752 // XXX: fake missing 'self' counter which is not available in iw survey output
9753 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9754 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9755
9756 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9757 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9758 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9759 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9760 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9761
9762 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",
9763 __func__,
9764 input_output_channelStats_array[i].ch_number,
9765 input_output_channelStats_array[i].ch_noise,
9766 input_output_channelStats_array[i].ch_utilization_total,
9767 input_output_channelStats_array[i].ch_utilization_busy,
9768 input_output_channelStats_array[i].ch_utilization_busy_rx,
9769 input_output_channelStats_array[i].ch_utilization_busy_tx,
9770 input_output_channelStats_array[i].ch_utilization_busy_self,
9771 input_output_channelStats_array[i].ch_utilization_busy_ext);
9772 }
9773#endif
9774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9775 return RETURN_OK;
9776}
9777#define HAL_NETLINK_IMPL
9778
9779/* Hostapd events */
9780
9781#ifndef container_of
9782#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9783#define container_of(ptr, type, member) \
9784 ((type *)((char *)ptr - offset_of(type, member)))
9785#endif /* container_of */
9786
9787struct ctrl {
9788 char sockpath[128];
9789 char sockdir[128];
9790 char bss[IFNAMSIZ];
9791 char reply[4096];
9792 int ssid_index;
9793 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9794 void (*overrun)(struct ctrl *ctrl);
9795 struct wpa_ctrl *wpa;
9796 unsigned int ovfl;
9797 size_t reply_len;
9798 int initialized;
9799 ev_timer retry;
9800 ev_timer watchdog;
9801 ev_stat stat;
9802 ev_io io;
9803};
9804static wifi_newApAssociatedDevice_callback clients_connect_cb;
9805static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9806static struct ctrl wpa_ctrl[MAX_APS];
9807static int initialized;
9808
9809static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9810{
9811 char cbuf[256] = {};
9812 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9813 struct cmsghdr *cmsg;
9814 unsigned int ovfl = ctrl->ovfl;
9815 unsigned int drop;
9816
9817 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9818 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9819 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9820 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9821
9822 drop = ovfl - ctrl->ovfl;
9823 ctrl->ovfl = ovfl;
9824
9825 return drop;
9826}
9827
9828static void ctrl_close(struct ctrl *ctrl)
9829{
9830 if (ctrl->io.cb)
9831 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9832 if (ctrl->retry.cb)
9833 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9834 if (!ctrl->wpa)
9835 return;
9836
9837 wpa_ctrl_detach(ctrl->wpa);
9838 wpa_ctrl_close(ctrl->wpa);
9839 ctrl->wpa = NULL;
9840 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9841}
9842
9843static void ctrl_process(struct ctrl *ctrl)
9844{
9845 const char *str;
9846 int drops;
9847 int level;
9848 int err;
9849
9850 /* Example events:
9851 *
9852 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9853 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9854 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9855 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9856 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9857 */
9858 if (!(str = index(ctrl->reply, '>')))
9859 return;
9860 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9861 return;
9862
9863 str++;
9864
9865 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9866 if (!(str = index(ctrl->reply, ' ')))
9867 return;
9868 wifi_associated_dev_t sta;
9869 memset(&sta, 0, sizeof(sta));
9870
9871 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9872 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9873 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9874
9875 sta.cli_Active=true;
9876
9877 (clients_connect_cb)(ctrl->ssid_index, &sta);
9878 goto handled;
9879 }
9880
9881 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9882 if (!(str = index(ctrl->reply, ' ')))
9883 return;
9884
9885 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9886 goto handled;
9887 }
9888
9889 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9890 printf("CTRL_WPA: handle TERMINATING event\n");
9891 goto retry;
9892 }
9893
9894 if (strncmp("AP-DISABLED", str, 11) == 0) {
9895 printf("CTRL_WPA: handle AP-DISABLED\n");
9896 goto retry;
9897 }
9898
9899 printf("Event not supported!!\n");
9900
9901handled:
9902
9903 if ((drops = ctrl_get_drops(ctrl))) {
9904 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
9905 if (ctrl->overrun)
9906 ctrl->overrun(ctrl);
9907 }
9908
9909 return;
9910
9911retry:
9912 printf("WPA_CTRL: closing\n");
9913 ctrl_close(ctrl);
9914 printf("WPA_CTRL: retrying from ctrl prcoess\n");
9915 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
9916}
9917
9918static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
9919{
9920 struct ctrl *ctrl = container_of(io, struct ctrl, io);
9921 int err;
9922
9923 memset(ctrl->reply, 0, sizeof(ctrl->reply));
9924 ctrl->reply_len = sizeof(ctrl->reply) - 1;
9925 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
9926 ctrl->reply[ctrl->reply_len] = 0;
9927 if (err < 0) {
9928 if (errno == EAGAIN || errno == EWOULDBLOCK)
9929 return;
9930 ctrl_close(ctrl);
9931 ev_timer_again(EV_A_ &ctrl->retry);
9932 return;
9933 }
9934
9935 ctrl_process(ctrl);
9936}
9937
9938static int ctrl_open(struct ctrl *ctrl)
9939{
9940 int fd;
9941
9942 if (ctrl->wpa)
9943 return 0;
9944
9945 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
9946 if (!ctrl->wpa)
9947 goto err;
9948
9949 if (wpa_ctrl_attach(ctrl->wpa) < 0)
9950 goto err_close;
9951
9952 fd = wpa_ctrl_get_fd(ctrl->wpa);
9953 if (fd < 0)
9954 goto err_detach;
9955
9956 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
9957 goto err_detach;
9958
9959 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
9960 ev_io_start(EV_DEFAULT_ &ctrl->io);
9961
9962 return 0;
9963
9964err_detach:
9965 wpa_ctrl_detach(ctrl->wpa);
9966err_close:
9967 wpa_ctrl_close(ctrl->wpa);
9968err:
9969 ctrl->wpa = NULL;
9970 return -1;
9971}
9972
9973static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
9974{
9975 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
9976
9977 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
9978 ctrl_open(ctrl);
9979}
9980
9981static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
9982{
9983 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
9984
9985 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
9986 if (ctrl_open(ctrl) == 0) {
9987 printf("WPA_CTRL: retry successful\n");
9988 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9989 }
9990}
9991
9992int ctrl_enable(struct ctrl *ctrl)
9993{
9994 if (ctrl->wpa)
9995 return 0;
9996
9997 if (!ctrl->stat.cb) {
9998 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
9999 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10000 }
10001
10002 if (!ctrl->retry.cb) {
10003 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10004 }
10005
10006 return ctrl_open(ctrl);
10007}
10008
10009static void
10010ctrl_msg_cb(char *buf, size_t len)
10011{
10012 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10013
10014 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10015 ctrl_process(ctrl);
10016}
10017
10018static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10019{
10020 int err;
10021
10022 if (!ctrl->wpa)
10023 return -1;
10024 if (*reply_len < 2)
10025 return -1;
10026
10027 (*reply_len)--;
10028 ctrl->reply_len = sizeof(ctrl->reply);
10029 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10030 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10031 if (err < 0)
10032 return err;
10033
10034 if (ctrl->reply_len > *reply_len)
10035 ctrl->reply_len = *reply_len;
10036
10037 *reply_len = ctrl->reply_len;
10038 memcpy(reply, ctrl->reply, *reply_len);
10039 reply[*reply_len - 1] = 0;
10040 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10041 return 0;
10042}
10043
10044static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10045{
10046 const char *pong = "PONG";
10047 const char *ping = "PING";
10048 char reply[1024];
10049 size_t len = sizeof(reply);
10050 int err;
10051 ULONG s, snum;
10052 INT ret;
10053 BOOL status;
10054
10055 printf("WPA_CTRL: watchdog cb\n");
10056
10057 ret = wifi_getSSIDNumberOfEntries(&snum);
10058 if (ret != RETURN_OK) {
10059 printf("%s: failed to get SSID count", __func__);
10060 return;
10061 }
10062
10063 if (snum > MAX_APS) {
10064 printf("more ssid than supported! %lu\n", snum);
10065 return;
10066 }
10067
10068 for (s = 0; s < snum; s++) {
10069 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10070 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10071 continue;
10072 }
10073 if (status == false) continue;
10074
10075 memset(reply, 0, sizeof(reply));
10076 len = sizeof(reply);
10077 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10078 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10079 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10080 continue;
10081
10082 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10083 ctrl_close(&wpa_ctrl[s]);
10084 printf("WPA_CTRL: ev_timer_again %d\n", s);
10085 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10086 }
10087}
10088
10089static int init_wpa()
10090{
10091 int ret = 0, i = 0;
10092 ULONG s, snum;
10093
10094 ret = wifi_getSSIDNumberOfEntries(&snum);
10095 if (ret != RETURN_OK) {
10096 printf("%s: failed to get SSID count", __func__);
10097 return RETURN_ERR;
10098 }
10099
10100 if (snum > MAX_APS) {
10101 printf("more ssid than supported! %lu\n", snum);
10102 return RETURN_ERR;
10103 }
10104
10105 for (s = 0; s < snum; s++) {
10106 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10107 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10108 wpa_ctrl[s].ssid_index = s;
10109 ctrl_enable(&wpa_ctrl[s]);
10110 }
10111
10112 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10113 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10114
10115 initialized = 1;
10116 printf("WPA_CTRL: initialized\n");
10117
10118 return RETURN_OK;
10119}
10120
10121void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10122{
10123 clients_connect_cb = callback_proc;
10124 if (!initialized)
10125 init_wpa();
10126}
10127
10128void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10129{
10130 clients_disconnect_cb = callback_proc;
10131 if (!initialized)
10132 init_wpa();
10133}
10134
10135INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10136{
10137 // TODO Implement me!
10138 return RETURN_ERR;
10139}
10140
10141INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10142{
10143 // TODO Implement me!
10144 return RETURN_ERR;
10145}
10146
10147INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10148{
10149 int i;
10150 char cmd[256];
10151 char channel_numbers_buf[256];
10152 char dfs_state_buf[256];
10153 char line[256];
10154 const char *ptr;
10155
10156 memset(cmd, 0, sizeof(cmd));
10157 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10158 memset(line, 0, sizeof(line));
10159 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10160 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10161
10162 if (radioIndex == 0) { // 2.4G - all allowed
10163 if (outputMapSize < 11) {
10164 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10165 return RETURN_ERR;
10166 }
10167
10168 for (i = 0; i < 11; i++) {
10169 outputMap[i].ch_number = i + 1;
10170 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10171 }
10172
10173 return RETURN_OK;
10174 }
10175
10176 if (radioIndex == 1) { // 5G
10177// Example output of iw list:
10178//
10179// Frequencies:
10180// * 5180 MHz [36] (17.0 dBm)
10181// * 5200 MHz [40] (17.0 dBm)
10182// * 5220 MHz [44] (17.0 dBm)
10183// * 5240 MHz [48] (17.0 dBm)
10184// * 5260 MHz [52] (23.0 dBm) (radar detection)
10185// DFS state: usable (for 78930 sec)
10186// DFS CAC time: 60000 ms
10187// * 5280 MHz [56] (23.0 dBm) (radar detection)
10188// DFS state: usable (for 78930 sec)
10189// DFS CAC time: 60000 ms
10190// * 5300 MHz [60] (23.0 dBm) (radar detection)
10191// DFS state: usable (for 78930 sec)
10192// DFS CAC time: 60000 ms
10193// * 5320 MHz [64] (23.0 dBm) (radar detection)
10194// DFS state: usable (for 78930 sec)
10195// DFS CAC time: 60000 ms
10196// * 5500 MHz [100] (disabled)
10197// * 5520 MHz [104] (disabled)
10198// * 5540 MHz [108] (disabled)
10199// * 5560 MHz [112] (disabled)
10200//
10201// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10202 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10203 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10204 return RETURN_ERR;
10205 }
10206
10207 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10208 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10209 return RETURN_ERR;
10210 }
10211
10212 ptr = channel_numbers_buf;
10213 i = 0;
10214 while (ptr = get_line_from_str_buf(ptr, line)) {
10215 if (i >= outputMapSize) {
10216 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10217 return RETURN_ERR;
10218 }
10219 sscanf(line, "%d", &outputMap[i].ch_number);
10220
10221 memset(cmd, 0, sizeof(cmd));
10222 // Below command should fetch string for DFS state (usable, available or unavailable)
10223 // Example line: "DFS state: usable (for 78930 sec)"
10224 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) {
10225 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10226 return RETURN_ERR;
10227 }
10228
10229 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10230 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10231 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10232 return RETURN_ERR;
10233 }
10234
10235 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10236
10237 if (!strcmp(dfs_state_buf, "usable")) {
10238 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10239 } else if (!strcmp(dfs_state_buf, "available")) {
10240 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10241 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10242 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10243 } else {
10244 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10245 }
10246 i++;
10247 }
10248
10249 return RETURN_OK;
10250 }
10251
10252 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10253 return RETURN_ERR;
10254}
10255
10256INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10257{
10258 // TODO Implement me!
10259 return RETURN_ERR;
10260}
10261
10262INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10263{
10264 return RETURN_OK;
10265}
10266
10267INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10268{
10269 // TODO Implement me!
10270 return RETURN_ERR;
10271}
10272
10273INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10274{
10275 // TODO API refrence Implementaion is present on RPI hal
10276 return RETURN_ERR;
10277}
10278
10279INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10280{
developera5005b62022-09-13 15:43:35 +080010281 char cmd[128]={'\0'};
10282 char buf[128]={'\0'};
10283 char *support;
10284 int maximum_tx = 0, current_tx = 0;
10285
10286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10287 if(txpwr_pcntg == NULL)
10288 return RETURN_ERR;
10289
10290 // Get the maximum tx power of the device
10291 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10292 _syscmd(cmd, buf, sizeof(buf));
10293 maximum_tx = strtol(buf, NULL, 10);
10294
10295 // Get the current tx power
10296 memset(cmd, 0, sizeof(cmd));
10297 memset(buf, 0, sizeof(buf));
10298 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10299 _syscmd(cmd, buf, sizeof(buf));
10300 current_tx = strtol(buf, NULL, 10);
10301
10302 // Get the power supported list and find the current power percentage in supported list
10303 memset(buf, 0, sizeof(buf));
10304 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10305 support = strtok(buf, ",");
10306 while(true)
10307 {
10308 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10309 *txpwr_pcntg = 0;
10310 wifi_dbg_printf("current power is not in supported list\n");
10311 return RETURN_ERR;
10312 }
10313 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10314 if (tmp == current_tx) {
10315 *txpwr_pcntg = strtol(support, NULL, 10);
10316 break;
10317 }
10318 support = strtok(NULL, ",");
10319 }
10320 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010321 return RETURN_OK;
10322}
10323
10324INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10325{
developer58599c22022-09-13 16:40:34 +080010326 // TODO precac feature.
10327 struct params params = {0};
10328 char config_file[128] = {0};
10329
10330 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10331
10332 params.name = "enable_background_radar";
10333 params.value = enable?"1":"0";
10334 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10335 wifi_hostapdWrite(config_file, &params, 1);
10336 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10337
10338 /* TODO precac feature */
10339
10340 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10341 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010342}
10343
10344INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10345{
developer58599c22022-09-13 16:40:34 +080010346 char config_file[128] = {0};
10347 char buf[64] = {0};
10348
10349 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10350 if (NULL == enable || NULL == precac)
10351 return RETURN_ERR;
10352
10353 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10354 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10355 if (strncmp(enable, "1", 1) == 0)
10356 *enable = true;
10357 else
10358 *enable = false;
10359
10360 /* TODO precac feature */
10361
10362 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10363 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010364}
10365
10366INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10367{
developer58599c22022-09-13 16:40:34 +080010368 *supported = TRUE;
10369 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010370}
10371
developer454b9462022-09-13 15:29:16 +080010372INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10373{
10374 char cmd[128] = {0};
10375 char buf[64] = {0};
10376 char band_str[8] = {0};
10377 char GI[8] = {0};
10378 int tmp = 0;
10379 BOOL ax_mode = FALSE;
10380 BOOL short_GI = FALSE;
10381 FILE *f = NULL;
10382 wifi_band band;
10383
10384 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10385
10386 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
10387 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10388 return RETURN_ERR;
10389 }
10390 if (strstr(buf, "ax") != NULL)
10391 ax_mode = TRUE;
10392
10393 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
10394 short_GI = TRUE;
10395 strcpy(GI, "0.4");
10396 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
10397 strcpy(GI, "1.6");
10398 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
10399 strcpy(GI, "3.2");
10400 else // default
10401 strcpy(GI, "0.8");
10402
10403 band = wifi_index_to_band(radio_index);
10404 if (band == band_2_4)
10405 strcpy(band_str, "2.4");
10406 else if (band == band_5)
10407 strcpy(band_str, "5");
10408 else if (band == band_6)
10409 strcpy(band_str, "6");
10410 else {
10411 wifi_dbg_printf("%s: invalid band\n");
10412 return RETURN_ERR;
10413 }
10414
10415 if (ax_mode == TRUE)
10416 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
10417 else
10418 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
10419 _syscmd(cmd, buf, sizeof(buf));
10420
10421 // Record GI for get GI function
10422 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10423 f = fopen(buf, "w");
10424 if (f != NULL) {
10425 fprintf(f, "%s", GI);
10426 }
10427 fclose(f);
10428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10429 return RETURN_OK;
10430}
10431
10432INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10433{
10434 char buf[32] = {0};
10435 char cmd[64] = {0};
10436
10437 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10438
10439 if (guard_interval == NULL)
10440 return RETURN_ERR;
10441
10442 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10443 _syscmd(cmd, buf, sizeof(buf));
10444
10445 if (strncmp(buf, "0.4", 3) == 0)
10446 *guard_interval = wifi_guard_interval_400;
10447 else if (strncmp(buf, "0.8", 3) == 0)
10448 *guard_interval = wifi_guard_interval_800;
10449 else if (strncmp(buf, "1.6", 3) == 0)
10450 *guard_interval = wifi_guard_interval_1600;
10451 else if (strncmp(buf, "3.2", 3) == 0)
10452 *guard_interval = wifi_guard_interval_3200;
10453 else
10454 *guard_interval = wifi_guard_interval_auto;
10455
10456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10457 return RETURN_OK;
10458}
10459
developer3cc61d12022-09-13 16:36:05 +080010460INT wifi_setBSSColor(INT radio_index, UCHAR color)
10461{
10462 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10463 struct params params = {0};
10464 char config_file[128] = {0};
10465 char bss_color[4] ={0};
10466
10467 params.name = "he_bss_color";
10468 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10469 params.value = bss_color;
10470 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10471 wifi_hostapdWrite(config_file, &params, 1);
10472 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10473
10474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10475 return RETURN_OK;
10476}
10477
10478INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10479{
10480 char config_file[128] = {0};
10481 char buf[64] = {0};
10482 char temp_output[128] = {'\0'};
10483
10484 wifi_dbg_printf("\nFunc=%s\n", __func__);
10485 if (NULL == color)
10486 return RETURN_ERR;
10487
10488 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10489 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10490
10491 if(strlen(buf) > 0) {
10492 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10493 } else {
10494 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10495 }
10496
10497 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10498 wifi_dbg_printf("\noutput_string=%s\n", color);
10499
10500 return RETURN_OK;
10501}
10502
developer06a01d92022-09-07 16:32:39 +080010503/* multi-psk support */
10504INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10505{
10506 char cmd[256];
10507
10508 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10509 AP_PREFIX,
10510 apIndex,
10511 mac[0],
10512 mac[1],
10513 mac[2],
10514 mac[3],
10515 mac[4],
10516 mac[5]
10517 );
10518 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10519 _syscmd(cmd, key->wifi_keyId, 64);
10520
10521
10522 return RETURN_OK;
10523}
10524
10525INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10526{
10527 FILE *fd = NULL;
10528 char fname[100];
10529 char cmd[128] = {0};
10530 char out[64] = {0};
10531 wifi_key_multi_psk_t * key = NULL;
10532 if(keysNumber < 0)
10533 return RETURN_ERR;
10534
10535 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10536 fd = fopen(fname, "w");
10537 if (!fd) {
10538 return RETURN_ERR;
10539 }
10540 key= (wifi_key_multi_psk_t *) keys;
10541 for(int i=0; i<keysNumber; ++i, key++) {
10542 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10543 }
10544 fclose(fd);
10545
10546 //reload file
10547 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10548 _syscmd(cmd, out, 64);
10549 return RETURN_OK;
10550}
10551
10552INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10553{
10554 FILE *fd = NULL;
10555 char fname[100];
10556 char * line = NULL;
10557 char * pos = NULL;
10558 size_t len = 0;
10559 ssize_t read = 0;
10560 INT ret = RETURN_OK;
10561 wifi_key_multi_psk_t *keys_it = NULL;
10562
10563 if (keysNumber < 1) {
10564 return RETURN_ERR;
10565 }
10566
10567 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10568 fd = fopen(fname, "r");
10569 if (!fd) {
10570 return RETURN_ERR;
10571 }
10572
10573 if (keys == NULL) {
10574 ret = RETURN_ERR;
10575 goto close;
10576 }
10577
10578 keys_it = keys;
10579 while ((read = getline(&line, &len, fd)) != -1) {
10580 //Strip trailing new line if present
10581 if (read > 0 && line[read-1] == '\n') {
10582 line[read-1] = '\0';
10583 }
10584
10585 if(strcmp(line,"keyid=")) {
10586 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10587 if (!(pos = index(line, ' '))) {
10588 ret = RETURN_ERR;
10589 goto close;
10590 }
10591 pos++;
10592 //Here should be 00:00:00:00:00:00
10593 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10594 printf("Not supported MAC: %s\n", pos);
10595 }
10596 if (!(pos = index(pos, ' '))) {
10597 ret = RETURN_ERR;
10598 goto close;
10599 }
10600 pos++;
10601
10602 //The rest is PSK
10603 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10604 keys_it++;
10605
10606 if(--keysNumber <= 0)
10607 break;
10608 }
10609 }
10610
10611close:
10612 free(line);
10613 fclose(fd);
10614 return ret;
10615}
10616/* end of multi-psk support */
10617
10618INT wifi_setNeighborReports(UINT apIndex,
10619 UINT numNeighborReports,
10620 wifi_NeighborReport_t *neighborReports)
10621{
10622 char cmd[256] = { 0 };
10623 char hex_bssid[13] = { 0 };
10624 char bssid[18] = { 0 };
10625 char nr[256] = { 0 };
10626 char ssid[256];
10627 char hex_ssid[256];
10628 INT ret;
10629
10630 /*rmeove all neighbors*/
10631 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10632 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);
10633 system(cmd);
10634
10635 for(unsigned int i = 0; i < numNeighborReports; i++)
10636 {
10637 memset(ssid, 0, sizeof(ssid));
10638 ret = wifi_getSSIDName(apIndex, ssid);
10639 if (ret != RETURN_OK)
10640 return RETURN_ERR;
10641
10642 memset(hex_ssid, 0, sizeof(hex_ssid));
10643 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10644 sprintf(hex_ssid + k,"%02x", ssid[j]);
10645
10646 snprintf(hex_bssid, sizeof(hex_bssid),
10647 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10648 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10649 snprintf(bssid, sizeof(bssid),
10650 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10651 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10652
10653 snprintf(nr, sizeof(nr),
10654 "%s" // bssid
10655 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10656 "%02hhx" // operclass
10657 "%02hhx" // channel
10658 "%02hhx", // phy_mode
10659 hex_bssid,
10660 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10661 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10662 neighborReports[i].opClass,
10663 neighborReports[i].channel,
10664 neighborReports[i].phyTable);
10665
10666 snprintf(cmd, sizeof(cmd),
10667 "hostapd_cli set_neighbor "
10668 "%s " // bssid
10669 "ssid=%s " // ssid
10670 "nr=%s " // nr
10671 "-i %s%d",
10672 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10673
10674 if (WEXITSTATUS(system(cmd)) != 0)
10675 {
10676 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10677 }
10678 }
10679
10680 return RETURN_OK;
10681}
10682
10683INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10684{
10685 return RETURN_OK;
10686}
10687
10688#ifdef _WIFI_HAL_TEST_
10689int main(int argc,char **argv)
10690{
10691 int index;
10692 INT ret=0;
10693 char buf[1024]="";
10694
10695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10696 if(argc<3)
10697 {
10698 if(argc==2)
10699 {
10700 if(!strcmp(argv[1], "init"))
10701 return wifi_init();
10702 if(!strcmp(argv[1], "reset"))
10703 return wifi_reset();
10704 if(!strcmp(argv[1], "wifi_getHalVersion"))
10705 {
10706 char buffer[64];
10707 if(wifi_getHalVersion(buffer)==RETURN_OK)
10708 printf("Version: %s\n", buffer);
10709 else
10710 printf("Error in wifi_getHalVersion\n");
10711 return RETURN_OK;
10712 }
10713 }
10714 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10715 exit(-1);
10716 }
10717
10718 index = atoi(argv[2]);
10719 if(strstr(argv[1], "wifi_getApName")!=NULL)
10720 {
10721 wifi_getApName(index,buf);
10722 printf("Ap name is %s \n",buf);
10723 return 0;
10724 }
10725 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10726 {
10727 BOOL b = FALSE;
10728 BOOL *output_bool = &b;
10729 wifi_getRadioAutoChannelEnable(index,output_bool);
10730 printf("Channel enabled = %d \n",b);
10731 return 0;
10732 }
10733 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10734 {
10735 wifi_getApWpaEncryptionMode(index,buf);
10736 printf("encryption enabled = %s\n",buf);
10737 return 0;
10738 }
10739 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10740 {
10741 BOOL b = FALSE;
10742 BOOL *output_bool = &b;
10743 wifi_getApSsidAdvertisementEnable(index,output_bool);
10744 printf("advertisment enabled = %d\n",b);
10745 return 0;
10746 }
10747 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10748 {
10749 if(argc <= 3 )
10750 {
10751 printf("Insufficient arguments \n");
10752 exit(-1);
10753 }
10754
10755 char sta[20] = {'\0'};
10756 ULLONG handle= 0;
10757 strcpy(sta,argv[3]);
10758 mac_address_t st;
10759 mac_addr_aton(st,sta);
10760
10761 wifi_associated_dev_tid_stats_t tid_stats;
10762 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10763 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10764 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);
10765 }
10766
10767 if(strstr(argv[1], "getApEnable")!=NULL) {
10768 BOOL enable;
10769 ret=wifi_getApEnable(index, &enable);
10770 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10771 }
10772 else if(strstr(argv[1], "setApEnable")!=NULL) {
10773 BOOL enable = atoi(argv[3]);
10774 ret=wifi_setApEnable(index, enable);
10775 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10776 }
10777 else if(strstr(argv[1], "getApStatus")!=NULL) {
10778 char status[64];
10779 ret=wifi_getApStatus(index, status);
10780 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
10781 }
10782 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
10783 {
10784 wifi_getSSIDNameStatus(index,buf);
10785 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
10786 return 0;
10787 }
10788 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
10789 wifi_ssidTrafficStats2_t stats={0};
10790 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
10791 printf("%s %d: returns %d\n", argv[1], index, ret);
10792 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
10793 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
10794 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
10795 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
10796 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
10797 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
10798 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
10799 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
10800 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
10801 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
10802 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
10803 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
10804 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
10805 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
10806 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
10807 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
10808 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
10809 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
10810 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
10811 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
10812 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
10813 }
10814 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
10815 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
10816 UINT array_size=0;
10817 UINT i=0;
10818 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
10819 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10820 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
10821 printf(" neighbor %d:\n", i);
10822 printf(" ap_SSID =%s\n", pt->ap_SSID);
10823 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
10824 printf(" ap_Mode =%s\n", pt->ap_Mode);
10825 printf(" ap_Channel =%d\n", pt->ap_Channel);
10826 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
10827 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10828 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
10829 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
10830 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
10831 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
10832 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10833 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
10834 printf(" ap_Noise =%d\n", pt->ap_Noise);
10835 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
10836 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
10837 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
10838 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
10839 }
10840 if(neighbor_ap_array)
10841 free(neighbor_ap_array); //make sure to free the list
10842 }
10843 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
10844 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
10845 UINT array_size=0;
10846 UINT i=0;
10847 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
10848 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10849 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
10850 printf(" associated_dev %d:\n", i);
10851 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
10852 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
10853 printf(" cli_SNR =%d\n", pt->cli_SNR);
10854 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
10855 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
10856 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
10857 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
10858 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
10859 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
10860 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
10861 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
10862 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
10863 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
10864 }
10865 if(associated_dev_array)
10866 free(associated_dev_array); //make sure to free the list
10867 }
10868
10869 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
10870 {
10871#define MAX_ARRAY_SIZE 64
10872 int i, array_size;
10873 char *p, *ch_str;
10874 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
10875
10876 if(argc != 5)
10877 {
10878 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
10879 exit(-1);
10880 }
10881 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
10882
10883 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
10884 {
10885 strtok_r(ch_str, ",", &p);
10886 input_output_channelStats_array[i].ch_number = atoi(ch_str);
10887 }
10888 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
10889 if(!array_size)
10890 array_size=1;//Need to print current channel statistics
10891 for(i=0; i<array_size; i++)
10892 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
10893 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
10894 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
10895 input_output_channelStats_array[i].ch_number,\
10896 input_output_channelStats_array[i].ch_noise,\
10897 input_output_channelStats_array[i].ch_utilization_busy_rx,\
10898 input_output_channelStats_array[i].ch_utilization_busy_tx,\
10899 input_output_channelStats_array[i].ch_utilization_busy,\
10900 input_output_channelStats_array[i].ch_utilization_busy_ext,\
10901 input_output_channelStats_array[i].ch_utilization_total);
10902 }
10903
10904 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
10905 {
10906 if(argc <= 3 )
10907 {
10908 printf("Insufficient arguments \n");
10909 exit(-1);
10910 }
10911 char mac_addr[20] = {'\0'};
10912 wifi_device_t output_struct;
10913 int dev_index = atoi(argv[3]);
10914
10915 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
10916 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
10917 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);
10918 }
10919
10920 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
10921 {
10922 if (argc <= 3)
10923 {
10924 printf("Insufficient arguments\n");
10925 exit(-1);
10926 }
10927 char args[256];
10928 wifi_NeighborReport_t *neighborReports;
10929
10930 neighborReports = calloc(argc - 2, sizeof(neighborReports));
10931 if (!neighborReports)
10932 {
10933 printf("Failed to allocate memory");
10934 exit(-1);
10935 }
10936
10937 for (int i = 3; i < argc; ++i)
10938 {
10939 char *val;
10940 int j = 0;
10941 memset(args, 0, sizeof(args));
10942 strncpy(args, argv[i], sizeof(args));
10943 val = strtok(args, ";");
10944 while (val != NULL)
10945 {
10946 if (j == 0)
10947 {
10948 mac_addr_aton(neighborReports[i - 3].bssid, val);
10949 } else if (j == 1)
10950 {
10951 neighborReports[i - 3].info = strtol(val, NULL, 16);
10952 } else if (j == 2)
10953 {
10954 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
10955 } else if (j == 3)
10956 {
10957 neighborReports[i - 3].channel = strtol(val, NULL, 16);
10958 } else if (j == 4)
10959 {
10960 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
10961 } else {
10962 printf("Insufficient arguments]n\n");
10963 exit(-1);
10964 }
10965 val = strtok(NULL, ";");
10966 j++;
10967 }
10968 }
10969
10970 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
10971 if (ret != RETURN_OK)
10972 {
10973 printf("wifi_setNeighborReports ret = %d", ret);
10974 exit(-1);
10975 }
10976 }
10977 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
10978 {
10979 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
10980 printf("%s.\n", buf);
10981 else
10982 printf("Error returned\n");
10983 }
10984 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
10985 {
10986 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
10987 printf("%s.\n", buf);
10988 else
10989 printf("Error returned\n");
10990 }
10991 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
10992 {
10993 if (argc <= 2)
10994 {
10995 printf("Insufficient arguments\n");
10996 exit(-1);
10997 }
10998 char buf[64]= {'\0'};
10999 wifi_getRadioOperatingChannelBandwidth(index,buf);
11000 printf("Current bandwidth is %s \n",buf);
11001 return 0;
11002 }
11003 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11004 {
11005 if (argc <= 5)
11006 {
11007 printf("Insufficient arguments\n");
11008 exit(-1);
11009 }
11010 UINT channel = atoi(argv[3]);
11011 UINT width = atoi(argv[4]);
11012 UINT beacon = atoi(argv[5]);
11013 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11014 printf("Result = %d", ret);
11015 }
11016
11017 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11018 return 0;
11019}
11020
11021#endif
11022
11023#ifdef WIFI_HAL_VERSION_3
11024
developer1e5aa162022-09-13 16:06:24 +080011025INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11026{
11027 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11028 if (bitMap & WIFI_BITRATE_1MBPS)
11029 strcat(BasicRate, "1,");
11030 if (bitMap & WIFI_BITRATE_2MBPS)
11031 strcat(BasicRate, "2,");
11032 if (bitMap & WIFI_BITRATE_5_5MBPS)
11033 strcat(BasicRate, "5.5,");
11034 if (bitMap & WIFI_BITRATE_6MBPS)
11035 strcat(BasicRate, "6,");
11036 if (bitMap & WIFI_BITRATE_9MBPS)
11037 strcat(BasicRate, "9,");
11038 if (bitMap & WIFI_BITRATE_11MBPS)
11039 strcat(BasicRate, "11,");
11040 if (bitMap & WIFI_BITRATE_12MBPS)
11041 strcat(BasicRate, "12,");
11042 if (bitMap & WIFI_BITRATE_18MBPS)
11043 strcat(BasicRate, "18,");
11044 if (bitMap & WIFI_BITRATE_24MBPS)
11045 strcat(BasicRate, "24,");
11046 if (bitMap & WIFI_BITRATE_36MBPS)
11047 strcat(BasicRate, "36,");
11048 if (bitMap & WIFI_BITRATE_48MBPS)
11049 strcat(BasicRate, "48,");
11050 if (bitMap & WIFI_BITRATE_54MBPS)
11051 strcat(BasicRate, "54,");
11052 if (strlen(BasicRate) != 0) // remove last comma
11053 BasicRate[strlen(BasicRate) - 1] = '\0';
11054 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11055 return RETURN_OK;
11056}
11057
11058INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11059{
11060 UINT BitMap = 0;
11061 char *rate;
11062
11063 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11064 rate = strtok(BasicRatesList, ",");
11065 while(rate != NULL)
11066 {
11067 if (strcmp(rate, "1") == 0)
11068 BitMap |= WIFI_BITRATE_1MBPS;
11069 else if (strcmp(rate, "2") == 0)
11070 BitMap |= WIFI_BITRATE_2MBPS;
11071 else if (strcmp(rate, "5.5") == 0)
11072 BitMap |= WIFI_BITRATE_5_5MBPS;
11073 else if (strcmp(rate, "6") == 0)
11074 BitMap |= WIFI_BITRATE_6MBPS;
11075 else if (strcmp(rate, "9") == 0)
11076 BitMap |= WIFI_BITRATE_9MBPS;
11077 else if (strcmp(rate, "11") == 0)
11078 BitMap |= WIFI_BITRATE_11MBPS;
11079 else if (strcmp(rate, "12") == 0)
11080 BitMap |= WIFI_BITRATE_12MBPS;
11081 else if (strcmp(rate, "18") == 0)
11082 BitMap |= WIFI_BITRATE_18MBPS;
11083 else if (strcmp(rate, "24") == 0)
11084 BitMap |= WIFI_BITRATE_24MBPS;
11085 else if (strcmp(rate, "36") == 0)
11086 BitMap |= WIFI_BITRATE_36MBPS;
11087 else if (strcmp(rate, "48") == 0)
11088 BitMap |= WIFI_BITRATE_48MBPS;
11089 else if (strcmp(rate, "54") == 0)
11090 BitMap |= WIFI_BITRATE_54MBPS;
11091 rate = strtok(NULL, ",");
11092 }
11093 *basicRateBitMap = BitMap;
11094 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11095 return RETURN_OK;
11096}
11097
11098// 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 +080011099INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11100{
developer1e5aa162022-09-13 16:06:24 +080011101 char buf[128] = {0};
11102 char cmd[128] = {0};
11103 char config_file[64] = {0};
11104 int bandwidth;
11105 int set_mode;
11106 wifi_radio_operationParam_t current_param;
11107
11108 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11109
11110 multiple_set = TRUE;
11111 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11112 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11113 return RETURN_ERR;
11114 }
11115 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11116 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11117 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11118 return RETURN_ERR;
11119 }
11120 }
11121 if (current_param.channelWidth != operationParam->channelWidth || (current_param.channel != operationParam->channel && !operationParam->autoChannelEnabled)) {
11122 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11123 bandwidth = 20;
11124 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11125 bandwidth = 40;
11126 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11127 bandwidth = 80;
11128 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11129 bandwidth = 160;
11130 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11131 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11132 return RETURN_ERR;
11133 }
11134 }
11135 if (current_param.variant != operationParam->variant) {
11136 // Two different definition bit map, so need to check every bit.
11137 if (operationParam->variant & WIFI_80211_VARIANT_A)
11138 set_mode |= WIFI_MODE_A;
11139 if (operationParam->variant & WIFI_80211_VARIANT_B)
11140 set_mode |= WIFI_MODE_B;
11141 if (operationParam->variant & WIFI_80211_VARIANT_G)
11142 set_mode |= WIFI_MODE_G;
11143 if (operationParam->variant & WIFI_80211_VARIANT_N)
11144 set_mode |= WIFI_MODE_N;
11145 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11146 set_mode |= WIFI_MODE_AC;
11147 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11148 set_mode |= WIFI_MODE_AX;
11149 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11150 memset(buf, 0, sizeof(buf));
11151 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11152 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11153 return RETURN_ERR;
11154 }
11155 }
11156 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11157 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11158 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11159 return RETURN_ERR;
11160 }
11161 }
11162 if (current_param.beaconInterval != operationParam->beaconInterval) {
11163 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11164 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11165 return RETURN_ERR;
11166 }
11167 }
11168 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11169 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11170 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11171 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11172 return RETURN_ERR;
11173 }
11174 }
11175 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11176 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11177 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11178 return RETURN_ERR;
11179 }
11180 }
11181 if (current_param.guardInterval != operationParam->guardInterval) {
11182 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11183 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11184 return RETURN_ERR;
11185 }
11186 }
11187 if (current_param.transmitPower != operationParam->transmitPower) {
11188 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11189 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11190 return RETURN_ERR;
11191 }
11192 }
11193 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11194 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11195 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11196 return RETURN_ERR;
11197 }
11198 }
11199 if (current_param.obssCoex != operationParam->obssCoex) {
11200 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11201 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11202 return RETURN_ERR;
11203 }
11204 }
11205 if (current_param.stbcEnable != operationParam->stbcEnable) {
11206 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11207 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11208 return RETURN_ERR;
11209 }
11210 }
11211 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11212 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11213 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11214 return RETURN_ERR;
11215 }
11216 }
11217
11218 // if enable is true, then restart the radio
11219 wifi_setRadioEnable(index, FALSE);
11220 if (operationParam->enable == TRUE)
11221 wifi_setRadioEnable(index, TRUE);
11222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11223
developer06a01d92022-09-07 16:32:39 +080011224 return RETURN_OK;
11225}
11226
11227INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11228{
developer1e5aa162022-09-13 16:06:24 +080011229 char band[64] = {0};
11230 char buf[256] = {0};
11231 char config_file[64] = {0};
11232 char cmd[128] = {0};
11233 int ret = RETURN_ERR;
11234 int mode = 0;
11235 ULONG channel = 0;
11236 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011237
11238 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11239 printf("Entering %s index = %d\n", __func__, (int)index);
11240
developer1e5aa162022-09-13 16:06:24 +080011241 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11242 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11243 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011244 {
developer1e5aa162022-09-13 16:06:24 +080011245 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011246 return RETURN_ERR;
11247 }
11248 operationParam->enable = enabled;
11249
11250 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011251 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011252 {
developer1e5aa162022-09-13 16:06:24 +080011253 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011254 return RETURN_ERR;
11255 }
11256
11257 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011258 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011259 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011260 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011261 else if (!strcmp(band, "6GHz"))
11262 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011263 else
11264 {
developer1e5aa162022-09-13 16:06:24 +080011265 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011266 band);
11267 }
11268
developer1e5aa162022-09-13 16:06:24 +080011269 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11270 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11271 operationParam->channel = 0;
11272 operationParam->autoChannelEnabled = TRUE;
11273 } else {
11274 operationParam->channel = strtol(buf, NULL, 10);
11275 operationParam->autoChannelEnabled = FALSE;
11276 }
11277
developer06a01d92022-09-07 16:32:39 +080011278 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011279 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11280 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11281 return RETURN_ERR;
11282 }
developer06a01d92022-09-07 16:32:39 +080011283 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11284 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11285 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer1e5aa162022-09-13 16:06:24 +080011286 else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11287 else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011288 else
11289 {
developer1e5aa162022-09-13 16:06:24 +080011290 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11291 return false;
developer06a01d92022-09-07 16:32:39 +080011292 }
11293
developer1e5aa162022-09-13 16:06:24 +080011294 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11295 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11296 return RETURN_ERR;
11297 }
11298 // Two different definition bit map, so need to check every bit.
11299 if (mode & WIFI_MODE_A)
11300 operationParam->variant |= WIFI_80211_VARIANT_A;
11301 if (mode & WIFI_MODE_B)
11302 operationParam->variant |= WIFI_80211_VARIANT_B;
11303 if (mode & WIFI_MODE_G)
11304 operationParam->variant |= WIFI_80211_VARIANT_G;
11305 if (mode & WIFI_MODE_N)
11306 operationParam->variant |= WIFI_80211_VARIANT_N;
11307 if (mode & WIFI_MODE_AC)
11308 operationParam->variant |= WIFI_80211_VARIANT_AC;
11309 if (mode & WIFI_MODE_AX)
11310 operationParam->variant |= WIFI_80211_VARIANT_AX;
11311 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11312 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11313 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011314 }
developer1e5aa162022-09-13 16:06:24 +080011315 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11316 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11317 return RETURN_ERR;
11318 }
11319 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11320 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11321 return RETURN_ERR;
11322 }
developer06a01d92022-09-07 16:32:39 +080011323
developer1e5aa162022-09-13 16:06:24 +080011324 memset(buf, 0, sizeof(buf));
11325 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11326 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11327 return RETURN_ERR;
11328 }
11329 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11330
11331 memset(buf, 0, sizeof(buf));
11332 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11333 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11334 return RETURN_ERR;
11335 }
11336 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11337
11338 memset(buf, 0, sizeof(buf));
11339 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11340 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11341
11342 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11343 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11344 return RETURN_ERR;
11345 }
11346 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11347 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11348 return RETURN_ERR;
11349 }
11350
11351 memset(buf, 0, sizeof(buf));
11352 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11353 if (strcmp(buf, "-1") == 0) {
11354 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11355 operationParam->ctsProtection = FALSE;
11356 } else {
11357 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11358 operationParam->ctsProtection = TRUE;
11359 }
11360
11361 memset(buf, 0, sizeof(buf));
11362 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11363 if (strcmp(buf, "0") == 0)
11364 operationParam->obssCoex = FALSE;
11365 else
11366 operationParam->obssCoex = TRUE;
11367
11368 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11369 _syscmd(cmd, buf, sizeof(buf));
11370 if (strlen(buf) != 0)
11371 operationParam->stbcEnable = TRUE;
11372 else
11373 operationParam->stbcEnable = FALSE;
11374
11375 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11376 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11377 return RETURN_ERR;
11378 }
11379
11380 // Below value is hardcoded
11381
11382 operationParam->numSecondaryChannels = 0;
11383 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11384 operationParam->channelSecondary[i] = 0;
11385 }
11386 operationParam->csa_beacon_count = 15;
11387 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011388
11389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11390 return RETURN_OK;
11391}
11392
11393static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11394{
11395 if (radioIndex != 0 && radioIndex != 1)
11396 {
11397 printf("%s: Wrong radio index (%d)\n", __func__, index);
11398 return -1;
11399 }
11400
11401 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
11402 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
11403
11404 return (arrayIndex * 2) + radioIndex;
11405}
11406
11407INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11408{
11409 INT ret;
11410 int i;
11411 BOOL enabled = false;
11412 char buf[256];
11413 wifi_secur_list *secur_item;
11414 int vap_index;
11415 INT mode;
11416 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
11417
11418 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11419 printf("Entering %s index = %d\n", __func__, (int)index);
11420
11421 map->vap_array[index].radio_index = index;
11422 for (i = 0; i < 5; i++)
11423 {
11424 vap_index = array_index_to_vap_index(index, i);
11425 if (vap_index < 0)
11426 {
11427 return RETURN_ERR;
11428 }
11429
11430 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
11431
11432 map->vap_array[i].vap_index = vap_index;
11433
11434 memset(buf, 0, sizeof(buf));
11435 wifi_getApName(vap_index, buf); // XXX: error handling
11436 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
11437
11438 ret = wifi_getSSIDEnable(vap_index, &enabled);
11439 if (ret != RETURN_OK)
11440 {
11441 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
11442 return RETURN_ERR;
11443 }
11444 map->vap_array[i].u.bss_info.enabled = enabled;
11445
11446 memset(buf, 0, sizeof(buf));
11447 wifi_getBaseBSSID(vap_index, buf);
11448 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11449 &map->vap_array[i].u.bss_info.bssid[0],
11450 &map->vap_array[i].u.bss_info.bssid[1],
11451 &map->vap_array[i].u.bss_info.bssid[2],
11452 &map->vap_array[i].u.bss_info.bssid[3],
11453 &map->vap_array[i].u.bss_info.bssid[4],
11454 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
11455
11456 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
11457 map->vap_array[i].u.bss_info.showSsid = enabled;
11458
11459 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
11460 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
11461 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
11462
11463 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11464 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
11465
11466 memset(buf, 0, sizeof(buf));
11467 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
11468 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
11469
11470 wifi_getApSecurityModeEnabled(vap_index, buf);
11471
11472 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
11473 {
11474 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
11475 return RETURN_ERR;
11476 }
11477 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
11478
11479 memset(buf, 0, sizeof(buf));
11480 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
11481 strncpy(map->vap_array[i].u.bss_info.security.u.key.key, buf, sizeof(map->vap_array[i].u.bss_info.security.u.key.key) - 1);
11482
11483 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
11484 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
11485
11486 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
11487 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
11488
11489 wifi_getApIsolationEnable(vap_index, &enabled);
11490 map->vap_array[i].u.bss_info.isolation = enabled;
11491 }
11492 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11493 return RETURN_OK;
11494}
11495
11496INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11497{
11498 unsigned int i;
11499 wifi_vap_info_t *vap_info = NULL;
11500 int acl_mode;
11501 char *sec_str = NULL;
11502
11503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11504 printf("Entering %s index = %d\n", __func__, (int)index);
11505 for (i = 0; i < map->num_vaps; i++)
11506 {
11507 vap_info = &map->vap_array[i];
11508 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11509
11510 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11511 else
11512 {
11513 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11514 else acl_mode = 1;
11515 }
11516 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11517 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11518 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11519
11520 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11521 if (sec_str)
11522 {
11523 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11524 }
11525 else
11526 {
11527 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11528 }
11529
11530 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11531 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11532
11533 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11534 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11535
11536 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11537
11538 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11539 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11540 }
11541 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11542 return RETURN_OK;
11543}
11544
11545int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11546{
11547 char *token, *next;
11548 const char s[2] = ",";
11549 int count =0;
11550
11551 /* get the first token */
11552 token = strtok_r(pchannels, s, &next);
11553
11554 /* walk through other tokens */
11555 while( token != NULL && count < MAX_CHANNELS) {
11556 chlistptr->channels_list[count++] = atoi(token);
11557 token = strtok_r(NULL, s, &next);
11558 }
11559
11560 return count;
11561}
11562
11563static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11564{
11565 INT status;
11566 wifi_channels_list_t *chlistp;
11567 CHAR output_string[64];
11568 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011569 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011570
11571 if(rcap == NULL)
11572 {
11573 return RETURN_ERR;
11574 }
11575
11576 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011577 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011578
developer1e5aa162022-09-13 16:06:24 +080011579 if (band == band_2_4)
11580 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11581 else if (band == band_5)
11582 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11583 else if (band == band_6)
11584 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011585
11586 chlistp = &(rcap->channel_list[0]);
11587 memset(pchannels, 0, sizeof(pchannels));
11588
11589 /* possible number of radio channels */
11590 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11591 {
11592 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11593 }
11594 /* Number of channels and list*/
11595 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11596
11597 /* autoChannelSupported */
11598 /* always ON with wifi_getRadioAutoChannelSupported */
11599 rcap->autoChannelSupported = TRUE;
11600
11601 /* DCSSupported */
11602 /* always ON with wifi_getRadioDCSSupported */
11603 rcap->DCSSupported = TRUE;
11604
11605 /* zeroDFSSupported - TBD */
11606 rcap->zeroDFSSupported = FALSE;
11607
11608 /* Supported Country List*/
11609 memset(output_string, 0, sizeof(output_string));
11610 status = wifi_getRadioCountryCode(radioIndex, output_string);
11611 if( status != 0 ) {
11612 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11613 return RETURN_ERR;
11614 } else {
11615 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11616 }
11617 if(!strcmp(output_string,"US")){
11618 rcap->countrySupported[0] = wifi_countrycode_US;
11619 rcap->countrySupported[1] = wifi_countrycode_CA;
11620 } else if (!strcmp(output_string,"CA")) {
11621 rcap->countrySupported[0] = wifi_countrycode_CA;
11622 rcap->countrySupported[1] = wifi_countrycode_US;
11623 } else {
11624 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11625 }
11626
11627 rcap->numcountrySupported = 2;
11628
11629 /* csi */
11630 rcap->csi.maxDevices = 8;
11631 rcap->csi.soudingFrameSupported = TRUE;
11632
11633 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
11634
11635 /* channelWidth - all supported bandwidths */
11636 int i=0;
11637 rcap->channelWidth[i] = 0;
11638 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11639 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11640 WIFI_CHANNELBANDWIDTH_40MHZ);
11641
11642 }
developer1e5aa162022-09-13 16:06:24 +080011643 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080011644 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11645 WIFI_CHANNELBANDWIDTH_40MHZ |
11646 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
11647 }
11648
11649
11650 /* mode - all supported variants */
11651 // rcap->mode[i] = WIFI_80211_VARIANT_H;
11652 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011653 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 +080011654 }
11655 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011656 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
11657 }
11658 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
11659 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011660 }
11661 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
11662 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
11663
11664 /* supportedBitRate - all supported bitrates */
11665 rcap->supportedBitRate[i] = 0;
11666 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11667 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11668 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
11669 }
developer1e5aa162022-09-13 16:06:24 +080011670 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080011671 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11672 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
11673 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
11674 }
11675
11676
11677 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
11678 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
11679 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
11680 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
11681 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
11682 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
11683 rcap->cipherSupported = 0;
11684 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
11685 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
11686
11687 return RETURN_OK;
11688}
11689
11690INT wifi_getHalCapability(wifi_hal_capability_t *cap)
11691{
11692 INT status, radioIndex;
11693 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
11694 int iter = 0;
11695 unsigned int j;
11696 wifi_interface_name_idex_map_t *iface_info;
11697
11698 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11699
11700 memset(cap, 0, sizeof(wifi_hal_capability_t));
11701
11702 /* version */
11703 cap->version.major = WIFI_HAL_MAJOR_VERSION;
11704 cap->version.minor = WIFI_HAL_MINOR_VERSION;
11705
11706 /* number of radios platform property */
11707 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
11708 _syscmd(cmd, output, sizeof(output));
11709 cap->wifi_prop.numRadios = atoi(output);
11710
11711 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
11712 {
11713 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
11714 if (status != 0) {
11715 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
11716 return RETURN_ERR;
11717 }
11718
11719 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
11720 {
11721 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
11722 {
11723 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
11724 return RETURN_ERR;
11725 }
11726 iface_info = &cap->wifi_prop.interface_map[iter];
11727 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
11728 iface_info->rdk_radio_index = radioIndex;
11729 memset(output, 0, sizeof(output));
11730 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
11731 {
11732 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
11733 }
11734 // TODO: bridge name
11735 // TODO: vlan id
11736 // TODO: primary
11737 iface_info->index = array_index_to_vap_index(radioIndex, j);
11738 memset(output, 0, sizeof(output));
11739 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
11740 {
11741 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
11742 }
11743 iter++;
11744 }
11745 }
11746
11747 cap->BandSteeringSupported = FALSE;
11748 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11749 return RETURN_OK;
11750}
11751
11752INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
11753{
developer587c1b62022-09-27 15:58:59 +080011754 char buf[128] = {0};
11755 char config_file[128] = {0};
11756 char password[64] = {0};
11757 char mfp[32] = {0};
11758 char wpa_mode[32] = {0};
11759 struct params params = {0};
11760
11761 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11762
11763 multiple_set = TRUE;
11764 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11765 if (security->mode == wifi_security_mode_none) {
11766 strcpy(wpa_mode, "None");
11767 } else if (security->mode == wifi_security_mode_wpa_personal)
11768 strcpy(wpa_mode, "WPA-Personal");
11769 else if (security->mode == wifi_security_mode_wpa2_personal)
11770 strcpy(wpa_mode, "WPA2-Personal");
11771 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
11772 strcpy(wpa_mode, "WPA-WPA2-Personal");
11773 else if (security->mode == wifi_security_mode_wpa_enterprise)
11774 strcpy(wpa_mode, "WPA-Enterprise");
11775 else if (security->mode == wifi_security_mode_wpa2_enterprise)
11776 strcpy(wpa_mode, "WPA2-Enterprise");
11777 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
11778 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
11779 else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
11780 strcpy(wpa_mode, "WPA3-Personal");
11781 else if (security->mode == wifi_security_mode_wpa3_enterprise)
11782 strcpy(wpa_mode, "WPA3-Enterprise");
11783
11784 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
11785
11786 strncpy(password, security->u.key.key, 63);
11787 password[63] = '\0';
11788 wifi_setApSecurityKeyPassphrase(ap_index, password);
11789
11790 if (security->mode != wifi_security_mode_none) {
11791 memset(&params, 0, sizeof(params));
11792 params.name = "wpa_pairwise";
11793 if (security->encr == wifi_encryption_tkip)
11794 params.value = "TKIP";
11795 else if (security->encr == wifi_encryption_aes)
11796 params.value = "CCMP";
11797 else if (security->encr == wifi_encryption_aes_tkip)
11798 params.value = "TKIP CCMP";
11799 wifi_hostapdWrite(config_file, &params, 1);
11800 }
11801
11802 if (security->mfp == wifi_mfp_cfg_disabled)
11803 strcpy(mfp, "Disable");
11804 else if (security->mfp == wifi_mfp_cfg_optional)
11805 strcpy(mfp, "Optional");
11806 else if (security->mfp == wifi_mfp_cfg_required)
11807 strcpy(mfp, "Required");
11808 wifi_setApSecurityMFPConfig(ap_index, mfp);
11809
11810 memset(&params, 0, sizeof(params));
11811 params.name = "transition_disable";
11812 if (security->wpa3_transition_disable == TRUE)
11813 params.value = "0x01";
11814 else
11815 params.value = "0x00";
11816 wifi_hostapdWrite(config_file, &params, 1);
11817
11818 memset(&params, 0, sizeof(params));
11819 params.name = "wpa_group_rekey";
11820 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
11821 params.value = buf;
11822 wifi_hostapdWrite(config_file, &params, 1);
11823
11824 memset(&params, 0, sizeof(params));
11825 params.name = "wpa_strict_rekey";
11826 params.value = security->strict_rekey?"1":"0";
11827 wifi_hostapdWrite(config_file, &params, 1);
11828
11829 memset(&params, 0, sizeof(params));
11830 params.name = "wpa_pairwise_update_count";
11831 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
11832 params.value = buf;
11833 wifi_hostapdWrite(config_file, &params, 1);
11834
11835 memset(&params, 0, sizeof(params));
11836 params.name = "disable_pmksa_caching";
11837 params.value = security->disable_pmksa_caching?"1":"0";
11838 wifi_hostapdWrite(config_file, &params, 1);
11839
11840 wifi_setApEnable(ap_index, FALSE);
11841 wifi_setApEnable(ap_index, TRUE);
11842
11843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11844
developer06a01d92022-09-07 16:32:39 +080011845 return RETURN_OK;
11846}
11847
11848INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
11849{
developer587c1b62022-09-27 15:58:59 +080011850 char buf[128] = {0};
11851 char config_file[128] = {0};
11852 int disable = 0;
11853 // struct params params = {0};
11854
11855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11856 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11857 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
11858 security->mode = wifi_security_mode_none;
11859 if (strlen(buf) != 0) {
11860 if (strcmp(buf, "WPA-Personal"))
11861 security->mode = wifi_security_mode_wpa_personal;
11862 else if (strcmp(buf, "WPA2-Personal"))
11863 security->mode = wifi_security_mode_wpa2_personal;
11864 else if (strcmp(buf, "WPA-WPA2-Personal"))
11865 security->mode = wifi_security_mode_wpa_wpa2_personal;
11866 else if (strcmp(buf, "WPA-Enterprise"))
11867 security->mode = wifi_security_mode_wpa_enterprise;
11868 else if (strcmp(buf, "WPA2-Enterprise"))
11869 security->mode = wifi_security_mode_wpa2_enterprise;
11870 else if (strcmp(buf, "WPA-WPA2-Enterprise"))
11871 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
11872 else if (strcmp(buf, "WPA3-Personal"))
11873 security->mode = wifi_security_mode_wpa3_personal;
11874 else if (strcmp(buf, "WPA3-Transition"))
11875 security->mode = wifi_security_mode_wpa3_transition;
11876 else if (strcmp(buf, "WPA3-Enterprise"))
11877 security->mode = wifi_security_mode_wpa3_enterprise;
11878 }
11879
11880 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
11881 if (security->mode == wifi_security_mode_none)
11882 security->encr = wifi_encryption_none;
11883 else {
11884 if (strcmp(buf, "TKIP") == 0)
11885 security->encr = wifi_encryption_tkip;
11886 else if (strcmp(buf, "CCMP") == 0)
11887 security->encr = wifi_encryption_aes;
11888 else
11889 security->encr = wifi_encryption_aes_tkip;
11890 }
11891
11892 memset(buf, 0, sizeof(buf));
11893 wifi_getApSecurityMFPConfig(ap_index, buf);
11894 if (strcmp(buf, "Disabled") == 0)
11895 security->mfp = wifi_mfp_cfg_disabled;
11896 else if (strcmp(buf, "Optional") == 0)
11897 security->mfp = wifi_mfp_cfg_optional;
11898 else if (strcmp(buf, "Required") == 0)
11899 security->mfp = wifi_mfp_cfg_required;
11900
11901 memset(buf, 0, sizeof(buf));
11902 security->wpa3_transition_disable = FALSE;
11903 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
11904 disable = strtol(buf, NULL, 16);
11905 if (disable != 0)
11906 security->wpa3_transition_disable = TRUE;
11907
11908 memset(buf, 0, sizeof(buf));
11909 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
11910 if (strlen(buf) == 0)
11911 security->rekey_interval = 86400;
11912 else
11913 security->rekey_interval = strtol(buf, NULL, 10);
11914
11915 memset(buf, 0, sizeof(buf));
11916 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
11917 if (strlen(buf) == 0)
11918 security->strict_rekey = 1;
11919 else
11920 security->strict_rekey = strtol(buf, NULL, 10);
11921
11922 memset(buf, 0, sizeof(buf));
11923 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
11924 if (strlen(buf) == 0)
11925 security->eapol_key_retries = 4;
11926 else
11927 security->eapol_key_retries = strtol(buf, NULL, 10);
11928
11929 memset(buf, 0, sizeof(buf));
11930 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
11931 if (strlen(buf) == 0)
11932 security->disable_pmksa_caching = FALSE;
11933 else
11934 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
11935
11936 /* TODO
11937 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
11938 */
11939 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
11940 security->eap_identity_req_timeout = 0;
11941 security->eap_identity_req_retries = 0;
11942 security->eap_req_timeout = 0;
11943 security->eap_req_retries = 0;
11944 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080011945 return RETURN_OK;
11946}
11947
11948#endif /* WIFI_HAL_VERSION_3 */
11949
11950#ifdef WIFI_HAL_VERSION_3_PHASE2
11951INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
11952{
developer13df9332022-09-27 16:53:22 +080011953 char cmd[128] = {0};
11954 char buf[128] = {0};
11955 char *mac_addr = NULL;
11956 BOOL status = FALSE;
11957 size_t len = 0;
11958
11959 if(ap_index > MAX_APS)
11960 return RETURN_ERR;
11961
11962 *output_numDevices = 0;
11963 wifi_getApEnable(ap_index, &status);
11964 if (status == FALSE)
11965 return RETURN_OK;
11966
11967 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
11968 _syscmd(cmd, buf, sizeof(buf));
11969
11970 mac_addr = strtok(buf, "\n");
11971 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
11972 *output_numDevices = i + 1;
11973 fprintf(stderr, "mac_addr: %s\n", mac_addr);
11974 addr_ptr = output_deviceMacAddressArray[i];
11975 mac_addr_aton(addr_ptr, mac_addr);
11976 mac_addr = strtok(NULL, "\n");
11977 }
11978
11979 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011980}
11981#else
11982INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
11983{
11984 char cmd[128];
11985 BOOL status = false;
11986
11987 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
11988 return RETURN_ERR;
11989
11990 output_buf[0] = '\0';
11991
11992 wifi_getApEnable(ap_index,&status);
11993 if (!status)
11994 return RETURN_OK;
11995
11996 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
11997 _syscmd(cmd, output_buf, output_buf_size);
11998
11999 return RETURN_OK;
12000}
12001#endif
developer2f513ab2022-09-13 14:26:06 +080012002
12003INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12004{
12005 char output[16]={'\0'};
12006 char config_file[MAX_BUF_SIZE] = {0};
12007
12008 if (!enable)
12009 return RETURN_ERR;
12010
12011 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12012 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12013
12014 if (strlen(output) == 0)
12015 *enable = FALSE;
12016 else if (strncmp(output, "1", 1) == 0)
12017 *enable = TRUE;
12018 else
12019 *enable = FALSE;
12020
12021 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12022 return RETURN_OK;
12023}
developer2d9c30f2022-09-13 15:06:14 +080012024
12025INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12026{
12027 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12028 return RETURN_ERR;
12029 *output_enable=TRUE;
12030 return RETURN_OK;
12031}
developerfd7d2892022-09-13 16:44:53 +080012032
12033INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12034{
12035 char cmd[128] = {0};
12036 char buf[128] = {0};
12037 char line[128] = {0};
12038 size_t len = 0;
12039 ssize_t read = 0;
12040 FILE *f = NULL;
12041 int index = 0;
12042 int exp = 0;
12043 int mantissa = 0;
12044 int duration = 0;
12045 int radio_index = 0;
12046 int max_radio_num = 0;
12047 uint twt_wake_interval = 0;
12048
12049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12050
12051 wifi_getMaxRadioNumber(&max_radio_num);
12052 radio_index = ap_index % max_radio_num;
12053 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12054 _syscmd(cmd, buf, sizeof(buf));
12055 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12056 if (*numSessionReturned > maxNumberSessions)
12057 *numSessionReturned = maxNumberSessions;
12058 else if (*numSessionReturned < 1) {
12059 *numSessionReturned = 0;
12060 return RETURN_OK;
12061 }
12062
12063 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12064 if ((f = popen(cmd, "r")) == NULL) {
12065 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12066 return RETURN_ERR;
12067 }
12068
12069 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12070 while((read = fgets(line, sizeof(line), f)) != NULL) {
12071 char *tmp = NULL;
12072 strcpy(buf, line);
12073 tmp = strtok(buf, " ");
12074 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12075 tmp = strtok(NULL, " ");
12076 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12077 tmp = strtok(NULL, " ");
12078 if (strstr(tmp, "t")) {
12079 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12080 }
12081 if (strstr(tmp, "a")) {
12082 twtSessions[index].twtParameters.operation.announced = TRUE;
12083 }
12084 tmp = strtok(NULL, " ");
12085 exp = strtol(tmp, NULL, 10);
12086 tmp = strtok(NULL, " ");
12087 mantissa = strtol(tmp, NULL, 10);
12088 tmp = strtok(NULL, " ");
12089 duration = strtol(tmp, NULL, 10);
12090
12091 // only implicit supported
12092 twtSessions[index].twtParameters.operation.implicit = TRUE;
12093 // only individual agreement supported
12094 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12095
12096 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12097 twt_wake_interval = mantissa * (1 << exp);
12098 if (twt_wake_interval/mantissa != (1 << exp)) {
12099 // Overflow handling
12100 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12101 } else {
12102 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12103 }
12104 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12105 index++;
12106 }
12107
12108 pclose(f);
12109 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12110 return RETURN_OK;
12111}