blob: 8543f945d068b60e500d2b561a017084184aa956 [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
66#define MAX_BUF_SIZE 128
67#define MAX_CMD_SIZE 1024
68#define MAX_POSSIBLE_CHANNEL_STRING_BUF 512
69#define IF_NAME_SIZE 50
70#define CONFIG_PREFIX "/nvram/hostapd"
71#define ACL_PREFIX "/tmp/hostapd-acl"
developer10adcc12022-09-13 14:39:17 +080072#define DENY_PREFIX "/tmp/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080073//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
74#define SOCK_PREFIX "/var/run/hostapd/wifi"
75#define VAP_STATUS_FILE "/tmp/vap-status"
developera3c68b92022-09-13 15:27:29 +080076#define ESSID_FILE "/tmp/essid"
developer454b9462022-09-13 15:29:16 +080077#define GUARD_INTERVAL_FILE "/tmp/guard-interval"
developera748dcf2022-09-13 15:56:48 +080078#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080079#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080080#define VLAN_FILE "/nvram/hostapd.vlan"
developer8d583982022-09-20 11:28:22 +080081#define PSK_FILE "/tmp/hostapd"
developer2de97692022-09-26 14:00:03 +080082#define CHAIN_MASK_FILE "/tmp/chain_mask"
developer54e6b9f2022-09-28 14:41:20 +080083#define AMSDU_FILE "/tmp/AMSDU"
developerf49437e2022-09-29 19:58:21 +080084#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080085#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080086
developer06a01d92022-09-07 16:32:39 +080087#define DRIVER_2GHZ "ath9k"
88#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080089#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080090
91/*
92 MAX_APS - Number of all AP available in system
93 2x Home AP
94 2x Backhaul AP
95 2x Guest AP
96 2x Secure Onboard AP
97 2x Service AP
98
99*/
100#define MAX_APS 10
101#define NUMBER_OF_RADIOS 2
102
103#ifndef AP_PREFIX
104#define AP_PREFIX "wifi"
105#endif
106
107#ifndef RADIO_PREFIX
108#define RADIO_PREFIX "wlan"
109#endif
110
111#define MAX_BUF_SIZE 128
112#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800113#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800114
115//Uncomment to enable debug logs
116//#define WIFI_DEBUG
117
118#ifdef WIFI_DEBUG
119#define wifi_dbg_printf printf
120#define WIFI_ENTRY_EXIT_DEBUG printf
121#else
122#define wifi_dbg_printf(format, args...) printf("")
123#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
124#endif
125
126#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
127#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
128#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
129#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
130#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
131#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
132#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
133#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
134#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
135#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
136
developer4fb0b922022-09-30 14:29:09 +0800137#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800138
139#define BW_FNAME "/nvram/bw_file.txt"
140
141#define PS_MAX_TID 16
142
143static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
144 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
145 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
148 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
150 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
152 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
153 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
155 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
156 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
158 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
160};
161
162typedef unsigned long long u64;
163
164/* Enum to define WiFi Bands */
165typedef enum
166{
167 band_invalid = -1,
168 band_2_4 = 0,
169 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800170 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800171} wifi_band;
172
developerdb744382022-09-13 15:34:54 +0800173typedef enum {
174 WIFI_MODE_A = 0x01,
175 WIFI_MODE_B = 0x02,
176 WIFI_MODE_G = 0x04,
177 WIFI_MODE_N = 0x08,
178 WIFI_MODE_AC = 0x10,
179 WIFI_MODE_AX = 0x20,
180} wifi_ieee80211_Mode;
181
developer06a01d92022-09-07 16:32:39 +0800182#ifdef WIFI_HAL_VERSION_3
183
184// Return number of elements in array
185#ifndef ARRAY_SIZE
186#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
187#endif /* ARRAY_SIZE */
188
189#ifndef ARRAY_AND_SIZE
190#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
191#endif /* ARRAY_AND_SIZE */
192
193#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
194
195typedef struct {
196 int32_t value;
197 int32_t param;
198 intptr_t key;
199 intptr_t data;
200} wifi_secur_list;
201
202wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
203wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
204char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800205static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800206
207static wifi_secur_list map_security[] =
208{
209 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
210 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
211 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
218};
219
220wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
221{
222 wifi_secur_list *item;
223 int i;
224
225 for (item = list,i = 0;i < list_sz; item++, i++) {
226 if ((int)(item->key) == key) {
227 return item;
228 }
229 }
230
231 return NULL;
232}
233
234char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
235{
236 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
237
238 if (!item) {
239 return "";
240 }
241
242 return (char *)(item->data);
243}
244
245wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
246{
247 wifi_secur_list *item;
248 int i;
249
250 for (item = list,i = 0;i < list_sz; item++, i++) {
251 if (strcmp((char *)(item->data), str) == 0) {
252 return item;
253 }
254 }
255
256 return NULL;
257}
258#endif /* WIFI_HAL_VERSION_3 */
259
260#ifdef HAL_NETLINK_IMPL
261typedef struct {
262 int id;
263 struct nl_sock* socket;
264 struct nl_cb* cb;
265} Netlink;
266
267static int mac_addr_aton(unsigned char *mac_addr, char *arg)
268{
269 unsigned int mac_addr_int[6]={};
270 sscanf(arg, "%x:%x:%x:%x:%x:%x", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
271 mac_addr[0] = mac_addr_int[0];
272 mac_addr[1] = mac_addr_int[1];
273 mac_addr[2] = mac_addr_int[2];
274 mac_addr[3] = mac_addr_int[3];
275 mac_addr[4] = mac_addr_int[4];
276 mac_addr[5] = mac_addr_int[5];
277 return 0;
278}
279
280static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
281{
282 unsigned int mac_addr_int[6]={};
283 mac_addr_int[0] = arg[0];
284 mac_addr_int[1] = arg[1];
285 mac_addr_int[2] = arg[2];
286 mac_addr_int[3] = arg[3];
287 mac_addr_int[4] = arg[4];
288 mac_addr_int[5] = arg[5];
289 snprintf(mac_addr, 20, "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
290 return;
291}
292
293static int ieee80211_frequency_to_channel(int freq)
294{
295 if (freq == 2484)
296 return 14;
297 else if (freq < 2484)
298 return (freq - 2407) / 5;
299 else if (freq >= 4910 && freq <= 4980)
300 return (freq - 4000) / 5;
301 else if (freq <= 45000)
302 return (freq - 5000) / 5;
303 else if (freq >= 58320 && freq <= 64800)
304 return (freq - 56160) / 2160;
305 else
306 return 0;
307}
308
309static int initSock80211(Netlink* nl) {
310 nl->socket = nl_socket_alloc();
311 if (!nl->socket) {
312 fprintf(stderr, "Failing to allocate the sock\n");
313 return -ENOMEM;
314 }
315
316 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
317
318 if (genl_connect(nl->socket)) {
319 fprintf(stderr, "Failed to connect\n");
320 nl_close(nl->socket);
321 nl_socket_free(nl->socket);
322 return -ENOLINK;
323 }
324
325 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
326 if (nl->id< 0) {
327 fprintf(stderr, "interface not found.\n");
328 nl_close(nl->socket);
329 nl_socket_free(nl->socket);
330 return -ENOENT;
331 }
332
333 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
334 if ((!nl->cb)) {
335 fprintf(stderr, "Failed to allocate netlink callback.\n");
336 nl_close(nl->socket);
337 nl_socket_free(nl->socket);
338 return ENOMEM;
339 }
340
341 return nl->id;
342}
343
344static int nlfree(Netlink *nl)
345{
346 nl_cb_put(nl->cb);
347 nl_close(nl->socket);
348 nl_socket_free(nl->socket);
349 return 0;
350}
351
352static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
353 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
354 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
355 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
356};
357
358static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
359};
360
361static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
362};
363
364typedef struct _wifi_channelStats_loc {
365 INT array_size;
366 INT ch_number;
367 BOOL ch_in_pool;
368 INT ch_noise;
369 BOOL ch_radar_noise;
370 INT ch_max_80211_rssi;
371 INT ch_non_80211_noise;
372 INT ch_utilization;
373 ULLONG ch_utilization_total;
374 ULLONG ch_utilization_busy;
375 ULLONG ch_utilization_busy_tx;
376 ULLONG ch_utilization_busy_rx;
377 ULLONG ch_utilization_busy_self;
378 ULLONG ch_utilization_busy_ext;
379} wifi_channelStats_t_loc;
380
381typedef struct wifi_device_info {
382 INT wifi_devIndex;
383 UCHAR wifi_devMacAddress[6];
384 CHAR wifi_devIPAddress[64];
385 BOOL wifi_devAssociatedDeviceAuthentiationState;
386 INT wifi_devSignalStrength;
387 INT wifi_devTxRate;
388 INT wifi_devRxRate;
389} wifi_device_info_t;
390
391#endif
392
393//For 5g Alias Interfaces
394static BOOL priv_flag = TRUE;
395static BOOL pub_flag = TRUE;
396static BOOL Radio_flag = TRUE;
397//wifi_setApBeaconRate(1, beaconRate);
398
developer1e5aa162022-09-13 16:06:24 +0800399BOOL multiple_set = FALSE;
400
developer06a01d92022-09-07 16:32:39 +0800401struct params
402{
403 char * name;
404 char * value;
405};
406
407static int _syscmd(char *cmd, char *retBuf, int retBufSize)
408{
409 FILE *f;
410 char *ptr = retBuf;
411 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
412
413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
414 if((f = popen(cmd, "r")) == NULL) {
415 fprintf(stderr,"\npopen %s error\n", cmd);
416 return RETURN_ERR;
417 }
418
419 while(!feof(f))
420 {
421 *ptr = 0;
422 if(bufSize>=128) {
423 bufbytes=128;
424 } else {
425 bufbytes=bufSize-1;
426 }
427
428 fgets(ptr,bufbytes,f);
429 readbytes=strlen(ptr);
430
431 if(!readbytes)
432 break;
433
434 bufSize-=readbytes;
435 ptr += readbytes;
436 }
437 cmd_ret = pclose(f);
438 retBuf[retBufSize-1]=0;
439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
440
441 return cmd_ret >> 8;
442}
443
developerc707e972022-09-13 15:38:02 +0800444wifi_band wifi_index_to_band(int apIndex)
445{
446 char cmd[128] = {0};
447 char buf[64] = {0};
448 int freq = 0;
449 wifi_band band = band_invalid;
450
451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
452 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
453 _syscmd(cmd, buf, sizeof(buf));
454 freq = strtol(buf, NULL, 10);
455 if (freq > 2401 && freq < 2495)
456 band = band_2_4;
457 else if (freq > 5160 && freq < 5915)
458 band = band_5;
459 else if (freq > 5955 && freq < 7125)
460 band = band_6;
461
462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
463 return band;
464}
465
developer06a01d92022-09-07 16:32:39 +0800466static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
467{
468 char cmd[MAX_CMD_SIZE]={'\0'};
469 char buf[MAX_BUF_SIZE]={'\0'};
470 int ret = 0;
471
472 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
473 ret = _syscmd(cmd, buf, sizeof(buf));
474 if ((ret != 0) && (strlen(buf) == 0))
475 return -1;
476 snprintf(output, output_size, "%s", buf);
477
478 return 0;
479}
480
481static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
482{
483 char cmd[MAX_CMD_SIZE]={'\0'};
484 char buf[MAX_BUF_SIZE]={'\0'};
485
486 for(int i=0;i<item_count;i++)
487 {
488 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
489 if (strlen(buf) == 0) //Insert
490 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
491 else //Update
492 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
493 if(_syscmd(cmd, buf, sizeof(buf)))
494 return -1;
495 }
496
497 return 0;
498}
499
500static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
501{
developer1e5aa162022-09-13 16:06:24 +0800502 if (multiple_set == TRUE)
503 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800504 char cmd[MAX_CMD_SIZE]="", output[32]="";
505 FILE *fp;
506 int i;
507 //NOTE RELOAD should be done in ApplySSIDSettings
508
509 for(i=0; i<item_count; i++, list++)
510 {
511 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
512 if((fp = popen(cmd, "r"))==NULL)
513 {
514 perror("popen failed");
515 return -1;
516 }
517 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
518 {
519 pclose(fp);
520 perror("fgets failed");
521 return -1;
522 }
523 pclose(fp);
524 }
525 return 0;
526}
527
528static int wifi_reloadAp(int apIndex)
529{
developer1e5aa162022-09-13 16:06:24 +0800530 if (multiple_set == TRUE)
531 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800532 char cmd[MAX_CMD_SIZE]="";
533 char buf[MAX_BUF_SIZE]="";
534
535 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
536 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
537 return RETURN_ERR;
538
539 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
540 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
541 return RETURN_ERR;
542
543 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
544 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
545 return RETURN_ERR;
546
547 return RETURN_OK;
548}
549
550
551//For Getting Current Interface Name from corresponding hostapd configuration
552void GetInterfaceName(char *interface_name, char *conf_file)
553{
554 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
555 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
556 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
557}
558
559INT File_Reading(CHAR *file, char *Value)
560{
561 FILE *fp = NULL;
562 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
563 int count = 0;
564
565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
566 fp = popen(file,"r");
567 if(fp == NULL)
568 return RETURN_ERR;
569
570 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
571 {
572 for(count=0;buf[count]!='\n';count++)
573 copy_buf[count]=buf[count];
574 copy_buf[count]='\0';
575 }
576 strcpy(Value,copy_buf);
577 pclose(fp);
578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
579
580 return RETURN_OK;
581}
582
583void wifi_RestartHostapd_2G()
584{
585 int Public2GApIndex = 4;
586
587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
588 wifi_setApEnable(Public2GApIndex, FALSE);
589 wifi_setApEnable(Public2GApIndex, TRUE);
590 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
591}
592
593void wifi_RestartHostapd_5G()
594{
595 int Public5GApIndex = 5;
596
597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
598 wifi_setApEnable(Public5GApIndex, FALSE);
599 wifi_setApEnable(Public5GApIndex, TRUE);
600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
601}
602
603void wifi_RestartPrivateWifi_2G()
604{
605 int PrivateApIndex = 0;
606
607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
608 wifi_setApEnable(PrivateApIndex, FALSE);
609 wifi_setApEnable(PrivateApIndex, TRUE);
610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
611}
612
613void wifi_RestartPrivateWifi_5G()
614{
615 int Private5GApIndex = 1;
616
617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
618 wifi_setApEnable(Private5GApIndex, FALSE);
619 wifi_setApEnable(Private5GApIndex, TRUE);
620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
621}
622
623static int writeBandWidth(int radioIndex,char *bw_value)
624{
625 char buf[MAX_BUF_SIZE];
626 char cmd[MAX_CMD_SIZE];
627
628 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
629 if(_syscmd(cmd, buf, sizeof(buf)))
630 {
631 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
632 _syscmd(cmd, buf, sizeof(buf));
633 return RETURN_OK;
634 }
635
636 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
637 _syscmd(cmd,buf,sizeof(buf));
638 return RETURN_OK;
639}
640
641static int readBandWidth(int radioIndex,char *bw_value)
642{
643 char buf[MAX_BUF_SIZE];
644 char cmd[MAX_CMD_SIZE];
645 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
646 _syscmd(cmd,buf,sizeof(buf));
647 if(NULL!=strstr(buf,"20MHz"))
648 {
649 strcpy(bw_value,"20MHz");
650 }
651 else if(NULL!=strstr(buf,"40MHz"))
652 {
653 strcpy(bw_value,"40MHz");
654 }
655 else if(NULL!=strstr(buf,"80MHz"))
656 {
657 strcpy(bw_value,"80MHz");
658 }
659 else
660 {
661 return RETURN_ERR;
662 }
663 return RETURN_OK;
664}
665
developer39a5efb2022-09-13 16:09:06 +0800666INT wifi_getMaxRadioNumber(INT *max_radio_num)
667{
668 char cmd[64] = {0};
669 char buf[4] = {0};
670
671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
672
673 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
674 _syscmd(cmd, buf, sizeof(buf));
675 *max_radio_num = strtoul(buf, NULL, 10);
676
677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
678
679 return RETURN_OK;
680}
681
developer5f222492022-09-13 15:21:52 +0800682// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800683INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
684{
developer5f222492022-09-13 15:21:52 +0800685 struct params params={'\0'};
686 char config_file[MAX_BUF_SIZE] = {0};
687 char buf[MAX_BUF_SIZE] = {'\0'};
688
689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
690 if (strlen (beaconRate) < 5)
691 return RETURN_ERR;
692 // Copy the numeric value
693 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
694 buf[strlen(beaconRate) - 4] = '\0';
695
696 params.name = "beacon_rate";
697 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
698 if (strncmp(buf, "5.5", 3) == 0) {
699 snprintf(buf, sizeof(buf), "55");
700 params.value = buf;
701 } else {
702 strcat(buf, "0");
703 params.value = buf;
704 }
705
706 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
707 wifi_hostapdWrite(config_file, &params, 1);
708 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
710
711 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800712}
713
714INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
715{
developer5f222492022-09-13 15:21:52 +0800716 char config_file[MAX_BUF_SIZE] = {'\0'};
717 char temp_output[MAX_BUF_SIZE] = {'\0'};
718 char buf[MAX_BUF_SIZE] = {'\0'};
719 float rate = 0;
720
721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
722 if (NULL == beaconRate)
723 return RETURN_ERR;
724
725 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
726 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
727 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
728 if(strlen(buf) > 0) {
729 rate = atof(buf)/10;
730 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
731 } else {
732 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
733 }
734 strncpy(beaconRate, temp_output, sizeof(temp_output));
735 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
736
737 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800738}
739
740INT wifi_setLED(INT radioIndex, BOOL enable)
741{
742 return 0;
743}
744INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
745{
746 return RETURN_OK;
747}
748/**********************************************************************************
749 *
750 * Wifi Subsystem level function prototypes
751 *
752**********************************************************************************/
753//---------------------------------------------------------------------------------------------------
754//Wifi system api
755//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
756INT wifi_getHalVersion(CHAR *output_string) //RDKB
757{
758 if(!output_string)
759 return RETURN_ERR;
760 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
761
762 return RETURN_OK;
763}
764
765
766/* wifi_factoryReset() function */
767/**
768* @description Clears internal variables to implement a factory reset of the Wi-Fi
769* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
770*
771* @param None
772*
773* @return The status of the operation.
774* @retval RETURN_OK if successful.
775* @retval RETURN_ERR if any error is detected
776*
777* @execution Synchronous
778* @sideeffect None
779*
780* @note This function must not suspend and must not invoke any blocking system
781* calls. It should probably just send a message to a driver event handler task.
782*
783*/
784INT wifi_factoryReset()
785{
786 char cmd[128];
787
788 /*delete running hostapd conf files*/
789 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
790 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
791 system(cmd);
792 system("systemctl restart hostapd.service");
793
794 return RETURN_OK;
795}
796
797/* wifi_factoryResetRadios() function */
798/**
799* @description Restore all radio parameters without touching access point parameters. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
800*
801* @param None
802* @return The status of the operation
803* @retval RETURN_OK if successful
804* @retval RETURN_ERR if any error is detected
805*
806* @execution Synchronous
807*
808* @sideeffect None
809*
810* @note This function must not suspend and must not invoke any blocking system
811* calls. It should probably just send a message to a driver event handler task.
812*
813*/
814INT wifi_factoryResetRadios()
815{
816 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
817 return RETURN_OK;
818
819 return RETURN_ERR;
820}
821
822
823/* wifi_factoryResetRadio() function */
824/**
825* @description Restore selected radio parameters without touching access point parameters
826*
827* @param radioIndex - Index of Wi-Fi Radio channel
828*
829* @return The status of the operation.
830* @retval RETURN_OK if successful.
831* @retval RETURN_ERR if any error is detected
832*
833* @execution Synchronous.
834* @sideeffect None.
835*
836* @note This function must not suspend and must not invoke any blocking system
837* calls. It should probably just send a message to a driver event handler task.
838*
839*/
840INT wifi_factoryResetRadio(int radioIndex) //RDKB
841{
developer5ff7f5f2022-09-13 15:12:16 +0800842 system("systemctl stop hostapd.service");
843
developer06a01d92022-09-07 16:32:39 +0800844 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
845 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800846 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800847 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800848 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800849 else
850 return RETURN_ERR;
851
developer5ff7f5f2022-09-13 15:12:16 +0800852 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800853 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
854 return RETURN_OK;
855}
856
857/* wifi_initRadio() function */
858/**
859* Description: This function call initializes the specified radio.
860* Implementation specifics may dictate the functionality since
861* different hardware implementations may have different initilization requirements.
862* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
863*
864* @return The status of the operation.
865* @retval RETURN_OK if successful.
866* @retval RETURN_ERR if any error is detected
867*
868* @execution Synchronous.
869* @sideeffect None.
870*
871* @note This function must not suspend and must not invoke any blocking system
872* calls. It should probably just send a message to a driver event handler task.
873*
874*/
875INT wifi_initRadio(INT radioIndex)
876{
877 //TODO: Initializes the wifi subsystem (for specified radio)
878 return RETURN_OK;
879}
880void macfilter_init()
881{
882 char count[4]={'\0'};
883 char buf[253]={'\0'};
884 char tmp[19]={'\0'};
885 int dev_count,block,mac_entry=0;
886 char res[4]={'\0'};
887 char acl_file_path[64] = {'\0'};
888 FILE *fp = NULL;
889 int index=0;
890 char iface[10]={'\0'};
891 char config_file[MAX_BUF_SIZE] = {0};
892
893
894 sprintf(acl_file_path,"/tmp/mac_filter.sh");
895
896 fp=fopen(acl_file_path,"w+");
897 sprintf(buf,"#!/bin/sh \n");
898 fprintf(fp,"%s\n",buf);
899
900 system("chmod 0777 /tmp/mac_filter.sh");
901
902 for(index=0;index<=1;index++)
903 {
904 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
905 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
906 sprintf(buf,"syscfg get %dcountfilter",index);
907 _syscmd(buf,count,sizeof(count));
908 mac_entry=atoi(count);
909
910 sprintf(buf,"syscfg get %dblockall",index);
911 _syscmd(buf,res,sizeof(res));
912 block = atoi(res);
913
914 //Allow only those macs mentioned in ACL
915 if(block==1)
916 {
917 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
918 fprintf(fp,"%s\n",buf);
919 for(dev_count=1;dev_count<=mac_entry;dev_count++)
920 {
921 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
922 _syscmd(buf,tmp,sizeof(tmp));
923 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
924 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
925 fprintf(fp,"%s\n",buf);
926 }
927 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
928 fprintf(fp,"%s\n",buf);
929 }
930
931 //Block all the macs mentioned in ACL
932 else if(block==2)
933 {
934 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
935 fprintf(fp,"%s\n",buf);
936
937 for(dev_count=1;dev_count<=mac_entry;dev_count++)
938 {
939 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
940 _syscmd(buf,tmp,sizeof(tmp));
941 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
942 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
943 fprintf(fp,"%s\n",buf);
944 }
945 }
946 }
947 fclose(fp);
948}
949
950// Initializes the wifi subsystem (all radios)
951INT wifi_init() //RDKB
952{
953 char interface[MAX_BUF_SIZE]={'\0'};
954 char bridge_name[MAX_BUF_SIZE]={'\0'};
955 INT len=0;
956
957 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
958 //Not intitializing macfilter for Turris-Omnia Platform for now
959 //macfilter_init();
960
961 system("/usr/sbin/iw reg set US");
962 system("systemctl start hostapd.service");
963 sleep(2);//sleep to wait for hostapd to start
964
965 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
966
967 return RETURN_OK;
968}
969
970/* wifi_reset() function */
971/**
972* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
973* Implementation specifics may dictate what is actualy reset since
974* different hardware implementations may have different requirements.
975* Parameters : None
976*
977* @return The status of the operation.
978* @retval RETURN_OK if successful.
979* @retval RETURN_ERR if any error is detected
980*
981* @execution Synchronous.
982* @sideeffect None.
983*
984* @note This function must not suspend and must not invoke any blocking system
985* calls. It should probably just send a message to a driver event handler task.
986*
987*/
988INT wifi_reset()
989{
990 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +0800991 system("systemctl stop hostapd.service");
992 sleep(2);
993 system("systemctl start hostapd.service");
994 sleep(5);
developer06a01d92022-09-07 16:32:39 +0800995 return RETURN_OK;
996}
997
998/* wifi_down() function */
999/**
1000* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1001* Implementation specifics may dictate some functionality since
1002* different hardware implementations may have different requirements.
1003*
1004* @param None
1005*
1006* @return The status of the operation
1007* @retval RETURN_OK if successful
1008* @retval RETURN_ERR if any error is detected
1009*
1010* @execution Synchronous
1011* @sideeffect None
1012*
1013* @note This function must not suspend and must not invoke any blocking system
1014* calls. It should probably just send a message to a driver event handler task.
1015*
1016*/
1017INT wifi_down()
1018{
1019 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001020 system("systemctl stop hostapd.service");
1021 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001022 return RETURN_OK;
1023}
1024
1025
1026/* wifi_createInitialConfigFiles() function */
1027/**
1028* @description This function creates wifi configuration files. The format
1029* and content of these files are implementation dependent. This function call is
1030* used to trigger this task if necessary. Some implementations may not need this
1031* function. If an implementation does not need to create config files the function call can
1032* do nothing and return RETURN_OK.
1033*
1034* @param None
1035*
1036* @return The status of the operation
1037* @retval RETURN_OK if successful
1038* @retval RETURN_ERR if any error is detected
1039*
1040* @execution Synchronous
1041* @sideeffect None
1042*
1043* @note This function must not suspend and must not invoke any blocking system
1044* calls. It should probably just send a message to a driver event handler task.
1045*
1046*/
1047INT wifi_createInitialConfigFiles()
1048{
1049 //TODO: creates initial implementation dependent configuration files that are later used for variable storage. Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
1050 return RETURN_OK;
1051}
1052
1053// outputs the country code to a max 64 character string
1054INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1055{
developer7543b3b2022-09-13 13:47:17 +08001056 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1057 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001058 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001059
1060 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1061 _syscmd(cmd, buf, sizeof(buf));
1062 if(strlen(buf) > 0)
1063 snprintf(output_string, 64, "%s", buf);
1064 else
1065 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001066
1067 return RETURN_OK;
1068}
1069
1070INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1071{
1072 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001073 char str[MAX_BUF_SIZE]={'\0'};
1074 char cmd[MAX_CMD_SIZE]={'\0'};
1075 struct params params;
1076 char config_file[MAX_BUF_SIZE] = {0};
1077
1078 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1079 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1080 return RETURN_ERR;
1081
1082 params.name = "country_code";
1083 params.value = CountryCode;
1084 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1085 int ret = wifi_hostapdWrite(config_file, &params, 1);
1086 if (ret) {
1087 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1088 ,__func__, ret);
1089 }
1090
1091 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1092 if (ret) {
1093 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1094 ,__func__, ret);
1095 }
1096 wifi_reloadAp(radioIndex);
1097 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1098
developer06a01d92022-09-07 16:32:39 +08001099 return RETURN_OK;
1100}
1101
developera748dcf2022-09-13 15:56:48 +08001102INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1103{
1104 char channel_util_file[64] = {0};
1105 char cmd[128] = {0};
1106 char buf[128] = {0};
1107 char line[128] = {0};
1108 char *param = NULL, *value = NULL;
1109 int read = 0;
1110 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1111 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1112 size_t len = 0;
1113 FILE *f = NULL;
1114
1115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1116
1117 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1118 _syscmd(cmd, buf, sizeof(buf));
1119 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1120
1121 memset(cmd, 0, sizeof(cmd));
1122 memset(buf, 0, sizeof(buf));
1123 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1124 if ((f = popen(cmd, "r")) == NULL) {
1125 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1126 return RETURN_ERR;
1127 }
1128
1129 read = getline(&line, &len, f);
1130 while (read != -1) {
1131 param = strtok(line, ":\t");
1132 value = strtok(NULL, " ");
1133 if(strstr(param, "frequency") != NULL) {
1134 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1135 }
1136 if(strstr(param, "noise") != NULL) {
1137 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1138 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1139 }
1140 if(strstr(param, "channel active time") != NULL) {
1141 ActiveTime = strtol(value, NULL, 10);
1142 }
1143 if(strstr(param, "channel busy time") != NULL) {
1144 BusyTime = strtol(value, NULL, 10);
1145 }
1146 if(strstr(param, "channel transmit time") != NULL) {
1147 TransmitTime = strtol(value, NULL, 10);
1148 }
1149 read = getline(&line, &len, f);
1150 }
1151 pclose(f);
1152
1153 // The file should store the last active, busy and transmit time
1154 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1155 f = fopen(channel_util_file, "r");
1156 if (f != NULL) {
1157 read = getline(&line, &len, f);
1158 preActiveTime = strtol(line, NULL, 10);
1159 read = getline(&line, &len, f);
1160 preBusyTime = strtol(line, NULL, 10);
1161 read = getline(&line, &len, f);
1162 preTransmitTime = strtol(line, NULL, 10);
1163 fclose(f);
1164 }
1165
1166 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1167 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1168
1169 f = fopen(channel_util_file, "w");
1170 if (f != NULL) {
1171 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1172 fclose(f);
1173 }
1174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1175 return RETURN_OK;
1176}
1177
developer06a01d92022-09-07 16:32:39 +08001178/**********************************************************************************
1179 *
1180 * Wifi radio level function prototypes
1181 *
1182**********************************************************************************/
1183
1184//Get the total number of radios in this wifi subsystem
1185INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1186{
1187 if (NULL == output)
1188 return RETURN_ERR;
1189 *output = 2;
1190
1191 return RETURN_OK;
1192}
1193
1194//Get the total number of SSID entries in this wifi subsystem
1195INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1196{
1197 if (NULL == output)
1198 return RETURN_ERR;
1199 *output = MAX_APS;
1200
1201 return RETURN_OK;
1202}
1203
1204//Get the Radio enable config parameter
1205INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1206{
1207 char interface_path[MAX_CMD_SIZE] = {0};
1208 FILE *fp = NULL;
1209
1210 if (NULL == output_bool)
1211 return RETURN_ERR;
1212
1213 *output_bool = FALSE;
1214 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1215 return RETURN_ERR;
1216
1217 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1218 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001219 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001220 {
developercf48e482022-09-13 14:49:50 +08001221 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001222 }
1223 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001224 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1225 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1226 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001227
developercf48e482022-09-13 14:49:50 +08001228 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1229 *output_bool = TRUE;
1230 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001231 return RETURN_OK;
1232}
1233
1234INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1235{
1236 char cmd[MAX_CMD_SIZE] = {0};
1237 char buf[MAX_CMD_SIZE] = {0};
1238 int apIndex, ret;
1239 FILE *fp = NULL;
1240
1241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1242 if(enable==FALSE)
1243 {
1244 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1245 {
1246 //Detaching %s%d from hostapd daemon
1247 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1248 _syscmd(cmd, buf, sizeof(buf));
1249 if(strncmp(buf, "OK", 2))
1250 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1251 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1252 _syscmd(cmd, buf, sizeof(buf));
1253 }
developer456aa3e2022-09-13 14:27:36 +08001254 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001255 _syscmd(cmd, buf, sizeof(buf));
1256 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001257 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001258 }
1259 else
1260 {
developer456aa3e2022-09-13 14:27:36 +08001261 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001262 _syscmd(cmd, buf, sizeof(buf));
1263 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001264 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001265 sleep(1);
1266 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1267 {
1268 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1269 fp = fopen(cmd, "r");
1270 if(!fp)
1271 {
1272 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1273 _syscmd(cmd, buf, sizeof(buf));
1274 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1275 _syscmd(cmd, buf, sizeof(buf));
1276 }
1277 if(fp)
1278 fclose(fp);
1279 }
1280 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1281 {
1282 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1283 ret = _syscmd(cmd, buf, sizeof(buf));
1284 if ( ret == RETURN_ERR)
1285 {
1286 fprintf(stderr, "VAP interface creation failed\n");
1287 continue;
1288 }
1289 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1290 _syscmd(cmd, buf, sizeof(buf));
1291 if(*buf == '1')
1292 {
1293 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1294 radioIndex, apIndex);
1295 _syscmd(cmd, buf, sizeof(buf));
1296 if(strncmp(buf, "OK", 2))
1297 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1298 }
1299 }
1300 }
1301
1302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1303 return RETURN_OK;
1304}
1305
1306//Get the Radio enable status
1307INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1308{
1309 if (NULL == output_bool)
1310 return RETURN_ERR;
1311
1312 return wifi_getRadioEnable(radioIndex, output_bool);
1313}
1314
1315//Get the Radio Interface name from platform, eg "wlan0"
1316INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1317{
1318 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1319 return RETURN_ERR;
1320 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1321
1322 return RETURN_OK;
1323}
1324
1325//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1326//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1327INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1328{
developerbcc556a2022-09-22 20:02:45 +08001329 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1330 // For max bit rate, we should always choose the best MCS
1331 char mode[64] = {0};
1332 char channel_bandwidth_str[16] = {0};
1333 char *tmp = NULL;
1334 UINT mode_map = 0;
1335 UINT num_subcarrier = 0;
1336 UINT code_bits = 0;
1337 float code_rate = 0; // use max code rate
1338 int NSS = 0;
1339 UINT Symbol_duration = 0;
1340 UINT GI_duration = 0;
1341 wifi_band band = band_invalid;
1342 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1343 BOOL enable = FALSE;
1344 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001345
1346 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1347 if (NULL == output_string)
1348 return RETURN_ERR;
1349
developerbcc556a2022-09-22 20:02:45 +08001350 wifi_getRadioEnable(radioIndex, &enable);
1351 if (enable == FALSE) {
1352 snprintf(output_string, 64, "0 Mb/s");
1353 return RETURN_OK;
1354 }
1355
1356 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1357 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1358 return RETURN_ERR;
1359 }
1360
1361 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1362 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1363 return RETURN_ERR;
1364 }
1365
1366 if (gi == wifi_guard_interval_3200)
1367 GI_duration = 32;
1368 else if (gi == wifi_guard_interval_1600)
1369 GI_duration = 16;
1370 else if (gi == wifi_guard_interval_800)
1371 GI_duration = 8;
1372 else // auto, 400
1373 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001374
developerbcc556a2022-09-22 20:02:45 +08001375 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1376 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1377 return RETURN_ERR;
1378 }
1379
1380 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1381 strcpy(channel_bandwidth_str, "160");
1382
1383 if (mode_map & WIFI_MODE_AX) {
1384 if (strstr(channel_bandwidth_str, "160") != NULL)
1385 num_subcarrier = 1960;
1386 else if (strstr(channel_bandwidth_str, "80") != NULL)
1387 num_subcarrier = 980;
1388 else if (strstr(channel_bandwidth_str, "40") != NULL)
1389 num_subcarrier = 468;
1390 else if (strstr(channel_bandwidth_str, "20") != NULL)
1391 num_subcarrier = 234;
1392 code_bits = 10;
1393 code_rate = (float)5/6;
1394 Symbol_duration = 128;
1395 } else if (mode_map & WIFI_MODE_AC) {
1396 if (strstr(channel_bandwidth_str, "160") != NULL)
1397 num_subcarrier = 468;
1398 else if (strstr(channel_bandwidth_str, "80") != NULL)
1399 num_subcarrier = 234;
1400 else if (strstr(channel_bandwidth_str, "40") != NULL)
1401 num_subcarrier = 108;
1402 else if (strstr(channel_bandwidth_str, "20") != NULL)
1403 num_subcarrier = 52;
1404 code_bits = 8;
1405 code_rate = (float)5/6;
1406 Symbol_duration = 32;
1407 } else if (mode_map & WIFI_MODE_N) {
1408 if (strstr(channel_bandwidth_str, "160") != NULL)
1409 num_subcarrier = 468;
1410 else if (strstr(channel_bandwidth_str, "80") != NULL)
1411 num_subcarrier = 234;
1412 else if (strstr(channel_bandwidth_str, "40") != NULL)
1413 num_subcarrier = 108;
1414 else if (strstr(channel_bandwidth_str, "20") != NULL)
1415 num_subcarrier = 52;
1416 code_bits = 6;
1417 code_rate = (float)3/4;
1418 Symbol_duration = 32;
1419 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1420 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1421 snprintf(output_string, 64, "65 Mb/s");
1422 return RETURN_OK;
1423 } else {
1424 snprintf(output_string, 64, "0 Mb/s");
1425 return RETURN_OK;
1426 }
developer06a01d92022-09-07 16:32:39 +08001427
developerbcc556a2022-09-22 20:02:45 +08001428 // Spatial streams
1429 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1430 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1431 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001432 }
developerbcc556a2022-09-22 20:02:45 +08001433
1434 // multiple 10 is to align duration unit (0.1 us)
1435 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1436 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1437
developer06a01d92022-09-07 16:32:39 +08001438 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1439
1440 return RETURN_OK;
1441}
1442#if 0
1443INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1444{
1445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1446 char cmd[64];
1447 char buf[1024];
1448 int apIndex;
1449
1450 if (NULL == output_string)
1451 return RETURN_ERR;
1452
1453 apIndex=(radioIndex==0)?0:1;
1454
1455 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1456 _syscmd(cmd,buf, sizeof(buf));
1457
1458 snprintf(output_string, 64, "%s", buf);
1459 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1460 return RETURN_OK;
1461}
1462#endif
1463
1464
1465//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1466//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1467INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1468{
developer963da0c2022-09-13 15:58:27 +08001469 wifi_band band = band_invalid;
1470
developer06a01d92022-09-07 16:32:39 +08001471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1472 if (NULL == output_string)
1473 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001474
1475 band = wifi_index_to_band(radioIndex);
1476
1477 memset(output_string, 0, 10);
1478 if (band == band_2_4)
1479 strcpy(output_string, "2.4GHz");
1480 else if (band == band_5)
1481 strcpy(output_string, "5GHz");
1482 else if (band == band_6)
1483 strcpy(output_string, "6GHz");
1484 else
1485 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1487
1488 return RETURN_OK;
1489#if 0
1490 char buf[MAX_BUF_SIZE]={'\0'};
1491 char str[MAX_BUF_SIZE]={'\0'};
1492 char cmd[MAX_CMD_SIZE]={'\0'};
1493 char *ch=NULL;
1494 char *ch2=NULL;
1495
1496 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1497 if (NULL == output_string)
1498 return RETURN_ERR;
1499
1500
1501 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1502
1503 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1504 {
1505 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1506 return RETURN_ERR;
1507 }
1508 ch=strchr(buf,'\n');
1509 *ch='\0';
1510 ch=strchr(buf,'=');
1511 if(ch==NULL)
1512 return RETURN_ERR;
1513
1514
1515 ch++;
1516
1517 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1518 strcpy(buf,"0");
1519 if(strlen(ch) == 1)
1520 ch=strcat(buf,ch);
1521
1522
1523 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1524
1525 if(_syscmd(cmd,str,64) == RETURN_ERR)
1526 {
1527 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1528 return RETURN_ERR;
1529 }
1530
1531
1532 ch2=strchr(str,'\n');
1533 //replace \n with \0
1534 *ch2='\0';
1535 ch2=strchr(str,'=');
1536 if(ch2==NULL)
1537 {
1538 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1539 return RETURN_ERR;
1540 }
1541 else
1542 wifi_dbg_printf("%s",ch2+1);
1543
1544
1545 ch2++;
1546
1547
1548 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1549
1550 memset(buf,'\0',sizeof(buf));
1551 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1552 {
1553 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1554 return RETURN_ERR;
1555 }
1556 if (strstr(buf,"2.4") != NULL )
1557 strcpy(output_string,"2.4GHz");
1558 else if(strstr(buf,"5.") != NULL )
1559 strcpy(output_string,"5GHz");
1560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1561
1562 return RETURN_OK;
1563#endif
1564}
1565
1566//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1567//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1568INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1569{
1570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1571 if (NULL == output_string)
1572 return RETURN_ERR;
1573 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1575
1576 return RETURN_OK;
1577#if 0
1578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1579 char buf[MAX_BUF_SIZE]={'\0'};
1580 char str[MAX_BUF_SIZE]={'\0'};
1581 char cmd[MAX_CMD_SIZE]={'\0'};
1582 char *ch=NULL;
1583 char *ch2=NULL;
1584 char ch1[5]="0";
1585
1586 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1587
1588 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1589 {
1590 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1591 return RETURN_ERR;
1592 }
1593
1594 ch=strchr(buf,'\n');
1595 *ch='\0';
1596 ch=strchr(buf,'=');
1597 if(ch==NULL)
1598 return RETURN_ERR;
1599 ch++;
1600
1601 if(strlen(ch)==1)
1602 {
1603 strcat(ch1,ch);
1604
1605 }
1606 else
1607 {
1608 strcpy(ch1,ch);
1609 }
1610
1611
1612
1613 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1614 if(_syscmd(cmd,str,64) == RETURN_ERR)
1615 {
1616 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1617 return RETURN_ERR;
1618 }
1619
1620
1621 ch2=strchr(str,'\n');
1622 //replace \n with \0
1623 *ch2='\0';
1624 ch2=strchr(str,'=');
1625 if(ch2==NULL)
1626 {
1627 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1628 return RETURN_ERR;
1629 }
1630 else
1631 wifi_dbg_printf("%s",ch2+1);
1632 ch2++;
1633
1634
1635 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1636 memset(buf,'\0',sizeof(buf));
1637 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1638 {
1639 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1640 return RETURN_ERR;
1641 }
1642
1643
1644 if(strstr(buf,"2.4")!=NULL)
1645 {
1646 strcpy(output_string,"2.4GHz");
1647 }
1648 if(strstr(buf,"5.")!=NULL)
1649 {
1650 strcpy(output_string,"5GHz");
1651 }
1652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1653 return RETURN_OK;
1654#endif
1655}
1656
1657//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1658//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1659INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1660{
developer963da0c2022-09-13 15:58:27 +08001661 char cmd[128]={0};
1662 char buf[128]={0};
1663 char temp_output[128] = {0};
1664 wifi_band band;
1665
1666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001667 if (NULL == output_string)
1668 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001669
1670 band = wifi_index_to_band(radioIndex);
1671 if (band == band_2_4) {
1672 strcat(temp_output, "b,g,");
1673 } else if (band == band_5) {
1674 strcat(temp_output, "a,");
1675 }
1676
1677 // ht capabilities
1678 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", radioIndex);
1679 _syscmd(cmd, buf, sizeof(buf));
1680 if (strncmp(buf, "0x00", 4) != 0) {
1681 strcat(temp_output, "n,");
1682 }
developer06a01d92022-09-07 16:32:39 +08001683
developer963da0c2022-09-13 15:58:27 +08001684 // vht capabilities
1685 if (band == band_5) {
1686 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1687 _syscmd(cmd, buf, sizeof(buf));
1688 if (strncmp(buf, "0x00000000", 10) != 0) {
1689 strcat(temp_output, "ac,");
1690 }
1691 }
1692
1693 // he capabilities
1694 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", radioIndex);
1695 _syscmd(cmd, buf, sizeof(buf));
1696 if (strncmp (buf, "0x0000", 6) != 0) {
1697 strcat(temp_output, "ax,");
1698 }
1699
1700 // Remove the last comma
1701 if (strlen(temp_output) != 0)
1702 temp_output[strlen(temp_output)-1] = '\0';
1703 strncpy(output_string, temp_output, strlen(temp_output));
1704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001705 return RETURN_OK;
1706}
1707
1708//Get the radio operating mode, and pure mode flag. eg: "ac"
1709//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1710INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1711{
1712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1713 if (NULL == output_string)
1714 return RETURN_ERR;
1715
1716 if (radioIndex == 0) {
1717 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1718 *gOnly = FALSE;
1719 *nOnly = TRUE;
1720 *acOnly = FALSE;
1721 } else {
1722 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1723 *gOnly = FALSE;
1724 *nOnly = FALSE;
1725 *acOnly = FALSE;
1726 }
1727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1728
1729 return RETURN_OK;
1730#if 0
1731 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1732 char buf[64] = {0};
1733 char config_file[MAX_BUF_SIZE] = {0};
1734
1735 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1736 return RETURN_ERR;
1737
1738 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1739 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1740
1741 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1742 if (strlen(buf) == 0)
1743 {
1744 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1745 return RETURN_ERR;
1746 }
1747 if(strcmp(buf,"g")==0)
1748 {
1749 wifi_dbg_printf("\nG\n");
1750 *gOnly=TRUE;
1751 *nOnly=FALSE;
1752 *acOnly=FALSE;
1753 }
1754 else if(strcmp(buf,"n")==0)
1755 {
1756 wifi_dbg_printf("\nN\n");
1757 *gOnly=FALSE;
1758 *nOnly=TRUE;
1759 *acOnly=FALSE;
1760 }
1761 else if(strcmp(buf,"ac")==0)
1762 {
1763 wifi_dbg_printf("\nac\n");
1764 *gOnly=FALSE;
1765 *nOnly=FALSE;
1766 *acOnly=TRUE;
1767 }
1768 /* hostapd-5G.conf has "a" as hw_mode */
1769 else if(strcmp(buf,"a")==0)
1770 {
1771 wifi_dbg_printf("\na\n");
1772 *gOnly=FALSE;
1773 *nOnly=FALSE;
1774 *acOnly=FALSE;
1775 }
1776 else
1777 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1778
1779 //for a,n mode
1780 if(radioIndex == 1)
1781 {
1782 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1783 if(strcmp(buf,"1")==0)
1784 {
1785 strncpy(output_string, "n", 1);
1786 *nOnly=FALSE;
1787 }
1788 }
1789
1790 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1792 return RETURN_OK;
1793#endif
1794}
1795
developerdb744382022-09-13 15:34:54 +08001796INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1797{
1798 char cmd[128] = {0};
1799 char buf[64] = {0};
1800 char config_file[64] = {0};
1801 wifi_band band;
1802
1803 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1804 if(NULL == output_string || NULL == pureMode)
1805 return RETURN_ERR;
1806
1807 // grep all of the ieee80211 protocol config set to 1
1808 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1809 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1810 _syscmd(cmd, buf, sizeof(buf));
1811
1812 band = wifi_index_to_band(radioIndex);
1813 // puremode is a bit map
1814 *pureMode = 0;
1815 if (band == band_2_4) {
1816 strcat(output_string, "b,g");
1817 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1818 if (strstr(buf, "n") != NULL) {
1819 strcat(output_string, ",n");
1820 *pureMode |= WIFI_MODE_N;
1821 }
1822 if (strstr(buf, "ax") != NULL) {
1823 strcat(output_string, ",ax");
1824 *pureMode |= WIFI_MODE_AX;
1825 }
1826 } else if (band == band_5) {
1827 strcat(output_string, "a");
1828 *pureMode |= WIFI_MODE_A;
1829 if (strstr(buf, "n") != NULL) {
1830 strcat(output_string, ",n");
1831 *pureMode |= WIFI_MODE_N;
1832 }
1833 if (strstr(buf, "ac") != NULL) {
1834 strcat(output_string, ",ac");
1835 *pureMode |= WIFI_MODE_AC;
1836 }
1837 if (strstr(buf, "ax") != NULL) {
1838 strcat(output_string, ",ax");
1839 *pureMode |= WIFI_MODE_AX;
1840 }
1841 } else if (band == band_6) {
1842 if (strstr(buf, "ax") != NULL) {
1843 strcat(output_string, "ax");
1844 *pureMode |= WIFI_MODE_AX;
1845 }
1846 }
1847
1848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1849 return RETURN_OK;
1850}
1851
1852// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001853INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1854{
1855 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1856 if (strcmp (channelMode,"11A") == 0)
1857 {
1858 writeBandWidth(radioIndex,"20MHz");
1859 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1860 printf("\nChannel Mode is 802.11a (5GHz)\n");
1861 }
1862 else if (strcmp (channelMode,"11NAHT20") == 0)
1863 {
1864 writeBandWidth(radioIndex,"20MHz");
1865 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1866 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1867 }
1868 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1869 {
1870 writeBandWidth(radioIndex,"40MHz");
1871 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1872 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1873 }
1874 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1875 {
1876 writeBandWidth(radioIndex,"40MHz");
1877 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1878 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1879 }
1880 else if (strcmp (channelMode,"11ACVHT20") == 0)
1881 {
1882 writeBandWidth(radioIndex,"20MHz");
1883 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1884 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1885 }
1886 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1887 {
1888 writeBandWidth(radioIndex,"40MHz");
1889 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1890 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1891 }
1892 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1893 {
1894 writeBandWidth(radioIndex,"40MHz");
1895 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1896 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1897 }
1898 else if (strcmp (channelMode,"11ACVHT80") == 0)
1899 {
1900 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1901 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1902 }
1903 else if (strcmp (channelMode,"11ACVHT160") == 0)
1904 {
1905 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1906 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1907 }
1908 else if (strcmp (channelMode,"11B") == 0)
1909 {
1910 writeBandWidth(radioIndex,"20MHz");
1911 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1912 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1913 }
1914 else if (strcmp (channelMode,"11G") == 0)
1915 {
1916 writeBandWidth(radioIndex,"20MHz");
1917 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1918 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1919 }
1920 else if (strcmp (channelMode,"11NGHT20") == 0)
1921 {
1922 writeBandWidth(radioIndex,"20MHz");
1923 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1924 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1925 }
1926 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1927 {
1928 writeBandWidth(radioIndex,"40MHz");
1929 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1930 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1931 }
1932 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1933 {
1934 writeBandWidth(radioIndex,"40MHz");
1935 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1936 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1937 }
1938 else
1939 {
1940 return RETURN_ERR;
1941 }
1942 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1943
1944 return RETURN_OK;
1945}
1946
developerdb744382022-09-13 15:34:54 +08001947// Set the radio operating mode, and pure mode flag.
1948INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1949{
1950 int num_hostapd_support_mode = 3; // n, ac, ax
1951 struct params list[num_hostapd_support_mode];
1952 char config_file[64] = {0};
1953 char bandwidth[16] = {0};
1954 int mode_check_bit = 1 << 3; // n mode
1955 wifi_ieee80211_Mode mode = (wifi_ieee80211_Mode)pureMode;
1956
1957 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1958 // Set radio mode
1959 list[0].name = "ieee80211n";
1960 list[1].name = "ieee80211ac";
1961 list[2].name = "ieee80211ax";
1962 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1963
1964 // check the bit map from n to ax, and set hostapd config
1965 if (mode & WIFI_MODE_N)
1966 list[0].value = "1";
1967 else
1968 list[0].value = "0";
1969 if (mode & WIFI_MODE_AC)
1970 list[1].value = "1";
1971 else
1972 list[1].value = "0";
1973 if (mode & WIFI_MODE_AX)
1974 list[2].value = "1";
1975 else
1976 list[2].value = "0";
1977 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1978
1979 if (channelMode == NULL || strlen(channelMode) == 0)
1980 return RETURN_OK;
1981 // Set bandwidth
1982 if (strstr(channelMode, "40") != NULL)
1983 strcpy(bandwidth, "40MHz");
1984 else if (strstr(channelMode, "80") != NULL)
1985 strcpy(bandwidth, "80MHz");
1986 else if (strstr(channelMode, "160") != NULL)
1987 strcpy(bandwidth, "160MHz");
1988 else // 11A, 11B, 11G....
1989 strcpy(bandwidth, "20MHz");
1990
1991 writeBandWidth(radioIndex, bandwidth);
1992 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
1993
1994 wifi_reloadAp(radioIndex);
1995 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1996
1997 return RETURN_OK;
1998}
1999
developer06a01d92022-09-07 16:32:39 +08002000//Get the list of supported channel. eg: "1-11"
2001//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2002INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2003{
developer6318ed52022-09-13 15:17:58 +08002004 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002005 if (NULL == output_string)
2006 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002007 char cmd[256] = {0};
2008 char buf[128] = {0};
2009 BOOL dfs_enable = false;
2010 // Parse possible channel number and separate them with commas.
2011 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2012 if (dfs_enable)
2013 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
2014 else
2015 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
2016
2017 _syscmd(cmd,buf,sizeof(buf));
2018 strncpy(output_string, buf, sizeof(buf));
2019
2020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2021 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002022#if 0
2023 char IFName[50] ={0};
2024 char buf[MAX_BUF_SIZE] = {0};
2025 char cmd[MAX_CMD_SIZE] = {0};
2026 int count = 0;
2027 if (NULL == output_string)
2028 return RETURN_ERR;
2029
2030 //snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2031 if(radioIndex == 0)
2032 {
2033 GetInterfaceName(IFName,"/nvram/hostapd0.conf");
2034 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 2'\\.' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | sed 's/^0//g' | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2035 }
2036 else if(radioIndex == 1)
2037 {
2038 GetInterfaceName(IFName,"/nvram/hostapd1.conf");
2039 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep '5\\.[1-9]' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2040 }
2041 _syscmd(cmd, buf, sizeof(buf));
2042 if(strlen(buf) > 0)
2043 strcpy(output_string,buf);
2044 else
2045 strcpy(output_string,"0");
2046#endif
2047 return RETURN_OK;
2048}
2049
2050//Get the list for used channel. eg: "1,6,9,11"
2051//The output_string is a max length 256 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2052INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2053{
2054 if (NULL == output_string)
2055 return RETURN_ERR;
2056 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
2057#if 0
2058 char IFName[50] ={0};
2059 char buf[MAX_BUF_SIZE] = {0};
2060 char cmd[MAX_CMD_SIZE] = {0};
2061 if (NULL == output_string)
2062 return RETURN_ERR;
2063
2064 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2065 if(radioIndex == 0)
2066 {
2067 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
2068 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 2'\\.' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | sed 's/^0//g' | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2069 }
2070 else if(radioIndex == 1)
2071 {
2072 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
2073 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 5'\\.[1-9]' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 |tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2074 }
2075 _syscmd(cmd,buf, sizeof(buf));
2076 if(strlen(buf) > 0)
2077 strcpy(output_string,buf);
2078 else
2079 strcpy(output_string,"0");
2080#endif
2081 return RETURN_OK;
2082}
2083
2084//Get the running channel number
2085INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2086{
developerda1ed692022-09-13 13:59:20 +08002087#ifdef MTK_IMPL
2088 if(!wifi_getApChannel(radioIndex, output_ulong))
2089 return RETURN_OK;
2090 else
2091 return RETURN_ERR;
2092#else
developer06a01d92022-09-07 16:32:39 +08002093 char cmd[1024] = {0}, buf[5] = {0};
2094
2095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2096 if (NULL == output_ulong)
2097 return RETURN_ERR;
2098
2099 snprintf(cmd, sizeof(cmd),
2100 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2101 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2102 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2103 _syscmd(cmd, buf, sizeof(buf));
2104
2105 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2106 if (*output_ulong <= 0) {
2107 *output_ulong = 0;
2108 return RETURN_ERR;
2109 }
2110
2111 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2112 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002113#endif
developer06a01d92022-09-07 16:32:39 +08002114}
2115
2116
2117INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2118{
2119 char cmd[1024] = {0}, buf[5] = {0};
2120 char interface_name[50] = {0};
2121
2122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2123 if (NULL == output_ulong)
2124 return RETURN_ERR;
2125
2126 wifi_getApName(apIndex,interface_name);
2127 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2128 _syscmd(cmd,buf,sizeof(buf));
2129 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2130 if (*output_ulong == 0) {
2131 return RETURN_ERR;
2132 }
2133
2134 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2135 return RETURN_OK;
2136}
2137
2138//Storing the previous channel value
2139INT wifi_storeprevchanval(INT radioIndex)
2140{
2141 char buf[256] = {0};
2142 char output[4]={'\0'};
2143 char config_file[MAX_BUF_SIZE] = {0};
2144 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2145 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2146 if(radioIndex == 0)
2147 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2148 else if(radioIndex == 1)
2149 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2150 system(buf);
2151 Radio_flag = FALSE;
2152 return RETURN_OK;
2153}
2154
2155//Set the running channel number
2156INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2157{
2158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2159 struct params params={'\0'};
2160 char str_channel[4]={'\0'};
2161 struct params list;
2162 char config_file[MAX_BUF_SIZE] = {0};
2163
2164 list.name = "channel";
2165
2166 if(Radio_flag == TRUE)
2167 wifi_storeprevchanval(radioIndex); //for autochannel
2168
2169 if(radioIndex == 0)
2170 {
2171 switch(channel)
2172 {
2173 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
2174 sprintf(str_channel,"%ld", channel);
2175 list.value = str_channel;
2176 break;
2177 default:
2178 return RETURN_ERR;
2179 }
2180 }
2181 else if(radioIndex == 1)
2182 {
2183 switch(channel)
2184 {
2185 case 36: case 40: case 44: case 48: case 52: case 56: case 60: case 64: case 144: case 149: case 153: case 157: case 161: case 165: case 169:
2186 sprintf(str_channel,"%ld", channel);
2187 list.value = str_channel;
2188 break;
2189 default:
2190 return RETURN_ERR;
2191 }
2192 }
2193
2194 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS;i++)
2195 {
2196 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2197 wifi_hostapdWrite(config_file,&list,1);
2198 }
2199
2200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2201 return RETURN_OK;
2202 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2203 }
2204
2205INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2206{
2207 struct params list;
2208 char str_idx[16];
2209 char config_file[MAX_BUF_SIZE];
2210
2211 list.name = "vht_oper_centr_freq_seg0_idx";
2212 snprintf(str_idx, sizeof(str_idx), "%d", channel);
2213 list.value = str_idx;
2214
2215 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2216 {
2217 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2218 wifi_hostapdWrite(config_file, &list, 1);
2219 }
2220
2221 return RETURN_OK;
2222}
2223
2224//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2225//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2226INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2227{
2228 //Set to wifi config only. Wait for wifi reset to apply.
2229 char buf[256] = {0};
2230 char str_channel[256] = {0};
2231 int count = 0;
2232 ULONG Value = 0;
2233 FILE *fp = NULL;
2234 if(enable == TRUE)
2235 {
2236 if(radioIndex == 0)
2237 {
2238 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
2239 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
2240 }
2241 else if(radioIndex == 1)
2242 {
2243 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
2244 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
2245 }
2246 if(fp == NULL) //first time boot-up
2247 {
2248 if(radioIndex == 0)
2249 Value = 6;
2250 else if(radioIndex == 1)
2251 Value = 36;
2252 }
2253 else
2254 {
2255 if(fgets(buf,sizeof(buf),fp) != NULL)
2256 {
2257 for(count = 0;buf[count]!='\n';count++)
2258 str_channel[count] = buf[count];
2259 str_channel[count] = '\0';
2260 Value = atol(str_channel);
2261 printf("%sValue is %ld \n",__FUNCTION__,Value);
2262 pclose(fp);
2263 }
2264 }
2265 Radio_flag = FALSE;//for storing previous channel value
2266 wifi_setRadioChannel(radioIndex,Value);
2267 return RETURN_OK;
2268 }
2269 return RETURN_ERR;
2270}
2271
developer0b246d12022-09-30 15:24:20 +08002272INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2273{
2274 if (output_bool == NULL)
2275 return RETURN_ERR;
2276
2277 *output_bool = TRUE;
2278
2279 return RETURN_OK;
2280}
2281
developer06a01d92022-09-07 16:32:39 +08002282INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2283{
2284 if (NULL == output_bool)
2285 return RETURN_ERR;
2286 *output_bool=FALSE;
2287 return RETURN_OK;
2288}
2289
2290INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2291{
2292 if (NULL == output_bool)
2293 return RETURN_ERR;
2294 *output_bool=FALSE;
2295 return RETURN_OK;
2296}
2297
2298INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2299{
2300 //Set to wifi config only. Wait for wifi reset to apply.
2301 return RETURN_OK;
2302}
2303
2304INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2305{
2306 return RETURN_OK;
2307}
2308
2309INT wifi_factoryResetAP(int apIndex)
2310{
2311 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2312 //factory reset is not done for now on Turris
2313 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2314 return RETURN_OK;
2315}
2316
2317//To set Band Steering AP group
2318//To-do
2319INT wifi_setBandSteeringApGroup(char *ApGroup)
2320{
2321 return RETURN_OK;
2322}
2323
developer1e5aa162022-09-13 16:06:24 +08002324INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2325{
2326 char config_file[128] = {'\0'};
2327 char buf[128] = {'\0'};
2328
2329 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2330 if (dtimInterval == NULL)
2331 return RETURN_ERR;
2332
2333 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2334 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2335
2336 if (strlen(buf) == 0) {
2337 *dtimInterval = 2;
2338 } else {
2339 *dtimInterval = strtoul(buf, NULL, 10);
2340 }
2341
2342 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2343 return RETURN_OK;
2344}
2345
developer06a01d92022-09-07 16:32:39 +08002346INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2347{
developer5f222492022-09-13 15:21:52 +08002348 struct params params={0};
2349 char config_file[MAX_BUF_SIZE] = {'\0'};
2350 char buf[MAX_BUF_SIZE] = {'\0'};
2351
2352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2353 if (dtimInterval < 1 || dtimInterval > 255) {
2354 return RETURN_ERR;
2355 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2356 }
2357
2358 params.name = "dtim_period";
2359 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2360 params.value = buf;
2361
2362 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2363 wifi_hostapdWrite(config_file, &params, 1);
2364 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2365
2366 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2367 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002368}
2369
2370//Check if the driver support the Dfs
2371INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2372{
2373 if (NULL == output_bool)
2374 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002375 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002376 return RETURN_OK;
2377}
2378
2379//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.
2380//The value of this parameter is a comma seperated list of channel number
2381INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2382{
2383 if (NULL == output_pool)
2384 return RETURN_ERR;
2385 if (radioIndex==1)
2386 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2387 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2388
2389 return RETURN_OK;
2390}
2391
2392INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2393{
2394 //Set to wifi config. And apply instantly.
2395 return RETURN_OK;
2396}
2397
2398INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2399{
2400 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2401 return RETURN_ERR;
2402 *output_interval_seconds=1800;
2403 *output_dwell_milliseconds=40;
2404
2405 return RETURN_OK;
2406}
2407
2408INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2409{
2410 //Set to wifi config. And apply instantly.
2411 return RETURN_OK;
2412}
2413
2414//Get the Dfs enable status
2415INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2416{
developer9964b5b2022-09-13 15:59:34 +08002417 char buf[16] = {0};
2418 FILE *f = NULL;
2419 wifi_band band;
2420
2421 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2422
2423 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002424 if (NULL == output_bool)
2425 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002426
2427 band = wifi_index_to_band(radioIndex);
2428 if (band != band_5)
2429 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002430
developer9964b5b2022-09-13 15:59:34 +08002431 f = fopen(DFS_ENABLE_FILE, "r");
2432 if (f != NULL) {
2433 fgets(buf, 2, f);
2434 if (strncmp(buf, "0", 0) == 0)
2435 *output_bool = FALSE;
2436 fclose(f);
2437 }
2438 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002439 return RETURN_OK;
2440}
2441
2442//Set the Dfs enable status
2443INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2444{
developer9964b5b2022-09-13 15:59:34 +08002445 char buf[128] = {0};
2446 char config_file[128] = {0};
2447 FILE *f = NULL;
2448 struct params params={0};
2449 wifi_band band;
2450
2451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2452
2453 band = wifi_index_to_band(radioIndex);
2454 if (band != band_5)
2455 return RETURN_OK;
2456
2457 f = fopen(DFS_ENABLE_FILE, "w");
2458 if (f == NULL)
2459 return RETURN_ERR;
2460 fprintf(f, "%d", enable);
2461 fclose(f);
2462
2463 params.name = "acs_exclude_dfs";
2464 sprintf(buf, "%d", enable?"1":"0");
2465 params.value = buf;
2466 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2467 wifi_hostapdWrite(config_file, &params, 1);
2468 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2469
2470 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2471
2472 wifi_reloadAp(radioIndex);
2473
2474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002475}
2476
2477//Check if the driver support the AutoChannelRefreshPeriod
2478INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2479{
2480 if (NULL == output_bool)
2481 return RETURN_ERR;
2482 *output_bool=FALSE; //not support
2483
2484 return RETURN_OK;
2485}
2486
2487//Get the ACS refresh period in seconds
2488INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2489{
2490 if (NULL == output_ulong)
2491 return RETURN_ERR;
2492 *output_ulong=300;
2493
2494 return RETURN_OK;
2495}
2496
2497//Set the ACS refresh period in seconds
2498INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2499{
2500 return RETURN_ERR;
2501}
2502
2503//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2504//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2505INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2506{
developer70490032022-09-13 15:45:20 +08002507 char cmd[128] = {0}, buf[64] = {0};
2508 char interface_name[64] = {0};
2509 int ret = 0, len=0;
2510 BOOL radio_enable = FALSE;
2511
2512 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2513
developer06a01d92022-09-07 16:32:39 +08002514 if (NULL == output_string)
2515 return RETURN_ERR;
2516
developer70490032022-09-13 15:45:20 +08002517 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2518 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002519
developer70490032022-09-13 15:45:20 +08002520 if (radio_enable != TRUE)
2521 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002522
developer70490032022-09-13 15:45:20 +08002523 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002524 ret = _syscmd(cmd, buf, sizeof(buf));
2525 len = strlen(buf);
2526 if((ret != 0) || (len == 0))
2527 {
2528 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2529 return RETURN_ERR;
2530 }
2531
2532 buf[len-1] = '\0';
2533 snprintf(output_string, 64, "%sMHz", buf);
2534 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2535
2536#if 0
2537 //TODO: revisit below implementation
2538 char output_buf[8]={0};
2539 char bw_value[10];
2540 char config_file[MAX_BUF_SIZE] = {0};
2541
2542 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2543 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2544 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2545 readBandWidth(radioIndex,bw_value);
2546
2547 if(strstr (output_buf,"0") != NULL )
2548 {
2549 strcpy(output_string,bw_value);
2550 }
2551 else if (strstr (output_buf,"1") != NULL)
2552 {
2553 strcpy(output_string,"80MHz");
2554 }
2555 else if (strstr (output_buf,"2") != NULL)
2556 {
2557 strcpy(output_string,"160MHz");
2558 }
2559 else if (strstr (output_buf,"3") != NULL)
2560 {
2561 strcpy(output_string,"80+80");
2562 }
2563 else
2564 {
2565 strcpy(output_string,"Auto");
2566 }
2567 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2568#endif
2569
2570 return RETURN_OK;
2571}
2572
2573//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002574INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002575{
developerf7a466e2022-09-29 11:55:56 +08002576 char config_file[128];
2577 char set_value[16];
2578 struct params params[2];
2579 int max_radio_num = 0;
2580
developer06a01d92022-09-07 16:32:39 +08002581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002582
developerf7a466e2022-09-29 11:55:56 +08002583 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002584 return RETURN_ERR;
2585
developerf7a466e2022-09-29 11:55:56 +08002586 if(strstr(bandwidth,"80+80") != NULL)
2587 strcpy(set_value, "3");
2588 else if(strstr(bandwidth,"160") != NULL)
2589 strcpy(set_value, "2");
2590 else if(strstr(bandwidth,"80") != NULL)
2591 strcpy(set_value, "1");
2592 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2593 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002594 else
2595 {
developerf7a466e2022-09-29 11:55:56 +08002596 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002597 return RETURN_ERR;
2598 }
2599
developerf7a466e2022-09-29 11:55:56 +08002600 params[0].name = "vht_oper_chwidth";
2601 params[0].value = set_value;
2602 params[1].name = "he_oper_chwidth";
2603 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002604
developerf7a466e2022-09-29 11:55:56 +08002605 wifi_getMaxRadioNumber(&max_radio_num);
2606 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002607 {
developerf7a466e2022-09-29 11:55:56 +08002608 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2609 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002610 }
2611
2612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2613 return RETURN_OK;
2614}
2615
2616//Getting current radio extension channel
2617INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2618{
2619 CHAR buf[150] = {0};
2620 CHAR cmd[150] = {0};
2621 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2622 _syscmd(cmd, buf, sizeof(buf));
2623 if(NULL != strstr(buf,"HT40+"))
2624 strcpy(Value,"AboveControlChannel");
2625 else if(NULL != strstr(buf,"HT40-"))
2626 strcpy(Value,"BelowControlChannel");
2627 return RETURN_OK;
2628}
2629
2630//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2631//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.
2632INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2633{
2634 if (NULL == output_string)
2635 return RETURN_ERR;
2636
2637 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2638#if 0
2639 CHAR Value[100] = {0};
2640 if (NULL == output_string)
2641 return RETURN_ERR;
2642 if(radioIndex == 0)
2643 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2644 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2645 {
2646 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2647 if(strcmp(Value,"40MHz") == 0)
2648 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2649 else
2650 strcpy(Value,"Auto");
2651 }
2652 strcpy(output_string,Value);
2653#endif
2654
2655 return RETURN_OK;
2656}
2657
2658//Set the extension channel.
2659INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2660{
2661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2662 struct params params={'\0'};
2663 char config_file[MAX_BUF_SIZE] = {0};
2664 char ext_channel[127]={'\0'};
2665
2666 params.name = "ht_capab";
2667
2668 if(radioIndex == 0)
2669 {
2670 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002671 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002672 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002673 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002674 else
developer3cc0f2e2022-09-15 18:25:39 +08002675 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002676 }
2677 else if(radioIndex == 1)
2678 {
2679 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002680 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002681 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002682 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002683 else
developer3cc0f2e2022-09-15 18:25:39 +08002684 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002685 }
2686
2687 params.value = ext_channel;
2688 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2689 {
2690 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2691 wifi_hostapdWrite(config_file, &params, 1);
2692 }
2693
2694 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2695 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2696 return RETURN_OK;
2697}
2698
2699//Get the guard interval value. eg "400nsec" or "800nsec"
2700//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.
2701INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2702{
developer454b9462022-09-13 15:29:16 +08002703 wifi_guard_interval_t GI;
2704
2705 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2706
2707 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002708 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002709
2710 if (GI == wifi_guard_interval_400)
2711 strcpy(output_string, "400nsec");
2712 else if (GI == wifi_guard_interval_800)
2713 strcpy(output_string, "800nsec");
2714 else if (GI == wifi_guard_interval_1600)
2715 strcpy(output_string, "1600nsec");
2716 else if (GI == wifi_guard_interval_3200)
2717 strcpy(output_string, "3200nsec");
2718 else
2719 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002720
developer454b9462022-09-13 15:29:16 +08002721 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002722 return RETURN_OK;
2723}
2724
2725//Set the guard interval value.
2726INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2727{
developer454b9462022-09-13 15:29:16 +08002728 wifi_guard_interval_t GI;
2729 int ret = 0;
2730
2731 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2732
2733 if (strcmp(string, "400nsec") == 0)
2734 GI = wifi_guard_interval_400;
2735 else if (strcmp(string , "800nsec") == 0 || strcmp(string, "auto") == 0)
2736 GI = wifi_guard_interval_800;
2737 else if (strcmp(string , "1600nsec") == 0)
2738 GI = wifi_guard_interval_1600;
2739 else if (strcmp(string , "3200nsec") == 0)
2740 GI = wifi_guard_interval_3200;
2741
2742 ret = wifi_setGuardInterval(radioIndex, GI);
2743
2744 if (ret == RETURN_ERR) {
2745 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2746 return RETURN_ERR;
2747 }
2748
2749 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2750 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002751}
2752
2753//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2754INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2755{
developerf49437e2022-09-29 19:58:21 +08002756 char buf[32]={0};
2757 char mcs_file[64] = {0};
2758 char cmd[64] = {0};
2759 int mode_bitmap = 0;
2760
2761 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2762 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002763 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002764 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2765
2766 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2767 _syscmd(cmd, buf, sizeof(buf));
2768 if (strlen(buf) > 0)
2769 *output_int = strtol(buf, NULL, 10);
2770 else {
2771 // output the max MCS for the current radio mode
2772 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2773 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2774 return RETURN_ERR;
2775 }
2776 if (mode_bitmap & WIFI_MODE_AX) {
2777 *output_int = 11;
2778 } else if (mode_bitmap & WIFI_MODE_AC) {
2779 *output_int = 9;
2780 } else if (mode_bitmap & WIFI_MODE_N) {
2781 *output_int = 7;
2782 }
2783 }
2784 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002785
2786 return RETURN_OK;
2787}
2788
2789//Set the Modulation Coding Scheme index
2790INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2791{
developerf49437e2022-09-29 19:58:21 +08002792 // Only HE mode can specify MCS capability. We don't support MCS in HT mode, because that would be ambiguous (MCS code 8~11 refer to 2 NSS in HT but 1 NSS in HE adn VHT).
2793 char config_file[64] = {0};
2794 char set_value[16] = {0};
2795 char mcs_file[32] = {0};
2796 wifi_band band = band_invalid;
2797 struct params set_config = {0};
2798 FILE *f = NULL;
2799
2800 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2801
2802 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2803
2804 if (MCS > 11 || MCS < 0) {
2805 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2806 return RETURN_ERR;
2807 }
2808
2809 if (MCS <= 7)
2810 strcpy(set_value, "0");
2811 else if (MCS <= 9)
2812 strcpy(set_value, "1");
2813 else
2814 strcpy(set_value, "2");
2815
2816 set_config.name = "he_basic_mcs_nss_set";
2817 set_config.value = set_value;
2818
2819 wifi_hostapdWrite(config_file, &set_config, 1);
2820 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2821
2822 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2823 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2824 f = fopen(mcs_file, "w");
2825 if (f == NULL) {
2826 fprintf(stderr, "%s: fopen failed\n", __func__);
2827 return RETURN_ERR;
2828 }
2829 fprintf(f, "%d", MCS);
2830 fclose(f);
2831
2832 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2833 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002834}
2835
2836//Get supported Transmit Power list, eg : "0,25,50,75,100"
2837//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.
2838INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2839{
2840 if (NULL == output_list)
2841 return RETURN_ERR;
2842 snprintf(output_list, 64,"0,25,50,75,100");
2843 return RETURN_OK;
2844}
2845
developera5005b62022-09-13 15:43:35 +08002846//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002847//The transmite power level is in units of full power for this radio.
2848INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2849{
2850 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002851 char buf[16]={0};
2852 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002853
developera5005b62022-09-13 15:43:35 +08002854 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002855 return RETURN_ERR;
2856
developera5005b62022-09-13 15:43:35 +08002857 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 +08002858 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002859
developera5005b62022-09-13 15:43:35 +08002860 *output_ulong = strtol(buf, NULL, 10);
2861
2862 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002863 return RETURN_OK;
2864}
2865
2866//Set Transmit Power
2867//The transmite power level is in units of full power for this radio.
2868INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2869{
developera5005b62022-09-13 15:43:35 +08002870 char *support;
developer06a01d92022-09-07 16:32:39 +08002871 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002872 char buf[128]={0};
2873 char txpower_str[64] = {0};
2874 int txpower = 0;
2875 int maximum_tx = 0;
2876
2877 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002878
developera5005b62022-09-13 15:43:35 +08002879 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 +08002880 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002881 maximum_tx = strtol(buf, NULL, 10);
2882
2883 // Get the Tx power supported list and check that is the input in the list
2884 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2885 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2886 support = strtok(buf, ",");
2887 while(true)
2888 {
2889 if(support == NULL) { // input not in the list
2890 wifi_dbg_printf("Input value is invalid.\n");
2891 return RETURN_ERR;
2892 }
2893 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2894 break;
2895 }
2896 support = strtok(NULL, ",");
2897 }
2898 txpower = TransmitPower*maximum_tx/100;
2899 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2900 _syscmd(cmd, buf, sizeof(buf));
2901 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002902
2903 return RETURN_OK;
2904}
2905
2906//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2907INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2908{
2909 if (NULL == Supported)
2910 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002911 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002912
2913 return RETURN_OK;
2914}
2915
2916//Get 80211h feature enable
2917INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2918{
developer3885fec2022-09-13 15:13:47 +08002919 char buf[64]={'\0'};
2920 char config_file[64] = {'\0'};
2921
2922 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2923 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002924 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002925
2926 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2927 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002928
developer3885fec2022-09-13 15:13:47 +08002929 if (strncmp(buf, "1", 1) == 0)
2930 *enable = TRUE;
2931 else
2932 *enable = FALSE;
2933
2934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002935 return RETURN_OK;
2936}
2937
2938//Set 80211h feature enable
2939INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2940{
developer3885fec2022-09-13 15:13:47 +08002941 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2942 struct params params={'\0'};
2943 char config_file[MAX_BUF_SIZE] = {0};
2944
2945 params.name = "ieee80211h";
2946
2947 if (enable) {
2948 params.value = "1";
2949 } else {
2950 params.value = "0";
2951 }
2952
2953 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2954 wifi_hostapdWrite(config_file, &params, 1);
2955
2956 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2957 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2958 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002959}
2960
2961//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.
2962INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2963{
2964 if (NULL == output)
2965 return RETURN_ERR;
2966 *output=100;
2967
2968 return RETURN_OK;
2969}
2970
2971//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.
2972INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2973{
2974 if (NULL == output)
2975 return RETURN_ERR;
2976 *output = -99;
2977
2978 return RETURN_OK;
2979}
2980
2981INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2982{
2983 return RETURN_ERR;
2984}
2985
2986
2987//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2988INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2989{
developer5f222492022-09-13 15:21:52 +08002990 char cmd[MAX_BUF_SIZE]={'\0'};
2991 char buf[MAX_CMD_SIZE]={'\0'};
2992
2993 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2994 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08002995 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002996
2997 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
2998 _syscmd(cmd, buf, sizeof(buf));
2999 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003000
developer5f222492022-09-13 15:21:52 +08003001 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003002 return RETURN_OK;
3003}
3004
3005INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3006{
developer5f222492022-09-13 15:21:52 +08003007 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3008 struct params params={'\0'};
3009 char buf[MAX_BUF_SIZE] = {'\0'};
3010 char config_file[MAX_BUF_SIZE] = {'\0'};
3011
3012 params.name = "beacon_int";
3013 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3014 params.value = buf;
3015
3016 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3017 wifi_hostapdWrite(config_file, &params, 1);
3018
3019 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3021 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003022}
3023
3024//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.
3025INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3026{
developer06a01d92022-09-07 16:32:39 +08003027 //TODO: need to revisit below implementation
3028 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003029 char temp_output[128] = {0};
3030 char temp_TransmitRates[64] = {0};
3031 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003032
3033 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3034 if (NULL == output)
3035 return RETURN_ERR;
3036 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003037 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3038
3039 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3040 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3041 } else {
3042 temp = strtok(temp_TransmitRates," ");
3043 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003044 {
developere9d0abd2022-09-13 15:40:57 +08003045 // Convert 100 kbps to Mbps
3046 temp[strlen(temp)-1]=0;
3047 if((temp[0]=='5') && (temp[1]=='\0'))
3048 {
3049 temp="5.5";
3050 }
3051 strcat(temp_output,temp);
3052 temp = strtok(NULL," ");
3053 if(temp!=NULL)
3054 {
3055 strcat(temp_output,",");
3056 }
developer06a01d92022-09-07 16:32:39 +08003057 }
developere9d0abd2022-09-13 15:40:57 +08003058 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003059 }
developer06a01d92022-09-07 16:32:39 +08003060 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003061 return RETURN_OK;
3062}
3063
3064INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3065{
3066 char *temp;
3067 char temp1[128];
3068 char temp_output[128];
3069 char temp_TransmitRates[128];
3070 char set[128];
3071 char sub_set[128];
3072 int set_count=0,subset_count=0;
3073 int set_index=0,subset_index=0;
3074 char *token;
3075 int flag=0, i=0;
3076 struct params params={'\0'};
3077 char config_file[MAX_BUF_SIZE] = {0};
3078
3079 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3080 if(NULL == TransmitRates)
3081 return RETURN_ERR;
3082 strcpy(sub_set,TransmitRates);
3083
3084 //Allow only supported Data transmit rate to be set
3085 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3086 token = strtok(sub_set,",");
3087 while( token != NULL ) /* split the basic rate to be set, by comma */
3088 {
3089 sub_set[subset_count]=atoi(token);
3090 subset_count++;
3091 token=strtok(NULL,",");
3092 }
3093 token=strtok(set,",");
3094 while(token!=NULL) /* split the supported rate by comma */
3095 {
3096 set[set_count]=atoi(token);
3097 set_count++;
3098 token=strtok(NULL,",");
3099 }
3100 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3101 {
3102 for(set_index=0;set_index < set_count;set_index++)
3103 {
3104 flag=0;
3105 if(sub_set[subset_index]==set[set_index])
3106 break;
3107 else
3108 flag=1; /* No match found */
3109 }
3110 if(flag==1)
3111 return RETURN_ERR; //If value not found return Error
3112 }
3113 strcpy(temp_TransmitRates,TransmitRates);
3114
3115 for(i=0;i<strlen(temp_TransmitRates);i++)
3116 {
3117 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3118 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3119 {
3120 continue;
3121 }
3122 else
3123 {
3124 return RETURN_ERR;
3125 }
3126 }
3127 strcpy(temp_output,"");
3128 temp = strtok(temp_TransmitRates,",");
3129 while(temp!=NULL)
3130 {
3131 strcpy(temp1,temp);
3132 if(radioIndex==1)
3133 {
3134 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3135 {
3136 return RETURN_ERR;
3137 }
3138 }
3139
3140 if(strcmp(temp,"5.5")==0)
3141 {
3142 strcpy(temp1,"55");
3143 }
3144 else
3145 {
3146 strcat(temp1,"0");
3147 }
3148 strcat(temp_output,temp1);
3149 temp = strtok(NULL,",");
3150 if(temp!=NULL)
3151 {
3152 strcat(temp_output," ");
3153 }
3154 }
3155 strcpy(TransmitRates,temp_output);
3156
3157 params.name= "basic_rates";
3158 params.value =TransmitRates;
3159
3160 wifi_dbg_printf("\n%s:",__func__);
3161 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3162 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3163 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3164 wifi_hostapdWrite(config_file,&params,1);
3165 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3166 return RETURN_OK;
3167}
3168
3169//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3170INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3171{
3172 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3173 FILE *fp = NULL;
3174 char path[256] = {0}, output_string[256] = {0};
3175 int count = 0;
3176 char *interface = NULL;
3177
3178 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3179 if (fp == NULL)
3180 {
3181 printf("Failed to run command in Function %s\n", __FUNCTION__);
3182 return RETURN_ERR;
3183 }
3184 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3185 {
3186 interface = strchr(path, '=');
3187
3188 if (interface != NULL)
3189 {
3190 strcpy(output_string, interface + 1);
3191 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3192 interface_name[count] = output_string[count];
3193
3194 interface_name[count] = '\0';
3195 }
3196 }
3197 pclose(fp);
3198 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3199 return RETURN_OK;
3200}
3201
3202INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3203{
3204 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3205 output_struct->radio_BytesSent = 0;
3206 output_struct->radio_BytesReceived = 0;
3207 output_struct->radio_PacketsSent = 0;
3208 output_struct->radio_PacketsReceived = 0;
3209 output_struct->radio_ErrorsSent = 0;
3210 output_struct->radio_ErrorsReceived = 0;
3211 output_struct->radio_DiscardPacketsSent = 0;
3212 output_struct->radio_DiscardPacketsReceived = 0;
3213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3214 return RETURN_OK;
3215}
3216
3217
3218INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3219{
3220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3221 CHAR buf[MAX_CMD_SIZE] = {0};
3222 CHAR Value[MAX_BUF_SIZE] = {0};
3223 FILE *fp = NULL;
3224
3225 if (ifname == NULL || strlen(ifname) <= 1)
3226 return RETURN_OK;
3227
3228 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3229 system(buf);
3230
3231 fp = fopen("/tmp/Radio_Stats.txt", "r");
3232 if(fp == NULL)
3233 {
3234 printf("/tmp/Radio_Stats.txt not exists \n");
3235 return RETURN_ERR;
3236 }
3237 fclose(fp);
3238
3239 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3240 File_Reading(buf, Value);
3241 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3242
3243 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3244 File_Reading(buf, Value);
3245 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3246
3247 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3248 File_Reading(buf, Value);
3249 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3250
3251 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3252 File_Reading(buf, Value);
3253 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3254
3255 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3256 File_Reading(buf, Value);
3257 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3258
3259 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3260 File_Reading(buf, Value);
3261 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3262
3263 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3264 File_Reading(buf, Value);
3265 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3266
3267 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3268 File_Reading(buf, Value);
3269 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3270
3271 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3272 return RETURN_OK;
3273}
3274
3275INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3276{
3277 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3278 CHAR buf[MAX_CMD_SIZE] = {0};
3279 FILE *fp = NULL;
3280 INT count = 0;
3281
3282 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3283 {
3284 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3285 File_Reading(buf, status);
3286 }
3287 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3288 return RETURN_OK;
3289}
3290
3291//Get detail radio traffic static info
3292INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3293{
3294
3295#if 0
3296 //ifconfig radio_x
3297 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3298 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3299 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3300 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3301
3302 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3303 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3304 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.
3305 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.
3306
3307 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3308 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].
3309 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3310 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.
3311 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
3312 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
3313 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
3314 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
3315 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
3316
3317 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
3318 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
3319 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
3320 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.
3321
3322 return RETURN_OK;
3323#endif
3324
developera91d99f2022-09-29 15:59:10 +08003325 CHAR interface_name[64] = {0};
3326 CHAR config_path[64] = {0};
3327 BOOL iface_status = FALSE;
3328 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003329
3330 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3331 if (NULL == output_struct)
3332 return RETURN_ERR;
3333
developera91d99f2022-09-29 15:59:10 +08003334 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3335 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003336
developera91d99f2022-09-29 15:59:10 +08003337 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003338
developera91d99f2022-09-29 15:59:10 +08003339 if (iface_status == TRUE)
3340 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3341 else
3342 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003343
developera91d99f2022-09-29 15:59:10 +08003344 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3345 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3346 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3347 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3348 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3349 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3350 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3351 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003352
3353 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3354 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].
3355 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3356 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.
3357 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
3358 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
3359 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
3360 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
3361 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
3362
3363 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
3364 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
3365 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
3366 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.
3367
3368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3369
3370 return RETURN_OK;
3371}
3372
3373//Set radio traffic static Measureing rules
3374INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3375{
3376 //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
3377 // Else, save the MeasuringRate and MeasuringInterval for future usage
3378
3379 return RETURN_OK;
3380}
3381
3382//To start or stop RadioTrafficStats
3383INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3384{
3385 //zqiu: If the RadioTrafficStats process running
3386 // if(enable)
3387 // return RETURN_OK.
3388 // else
3389 // Stop RadioTrafficStats process
3390 // Else
3391 // if(enable)
3392 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3393 // else
3394 // return RETURN_OK.
3395
3396 return RETURN_OK;
3397}
3398
3399//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
3400INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3401{
3402 //zqiu: Please ignor signalIndex.
3403 if (NULL == SignalLevel)
3404 return RETURN_ERR;
3405 *SignalLevel=(radioIndex==0)?-19:-19;
3406
3407 return RETURN_OK;
3408}
3409
3410//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3411INT wifi_applyRadioSettings(INT radioIndex)
3412{
3413 return RETURN_OK;
3414}
3415
3416//Get the radio index assocated with this SSID entry
3417INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3418{
3419 if (NULL == radioIndex)
3420 return RETURN_ERR;
3421 *radioIndex=ssidIndex%2;
3422
3423 return RETURN_OK;
3424}
3425
3426//Device.WiFi.SSID.{i}.Enable
3427//Get SSID enable configuration parameters (not the SSID enable status)
3428INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3429{
3430 if (NULL == output_bool)
3431 return RETURN_ERR;
3432
3433 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3434 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3435 return wifi_getApEnable(ssidIndex, output_bool);
3436}
3437
3438//Device.WiFi.SSID.{i}.Enable
3439//Set SSID enable configuration parameters
3440INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3441{
3442 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3443 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3444 return wifi_setApEnable(ssidIndex, enable);
3445}
3446
3447//Device.WiFi.SSID.{i}.Status
3448//Get the SSID enable status
3449INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3450{
3451 char cmd[MAX_CMD_SIZE]={0};
3452 char buf[MAX_BUF_SIZE]={0};
3453 BOOL output_bool;
3454
3455 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3456 if (NULL == output_string)
3457 return RETURN_ERR;
3458 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3459 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3460
3461 wifi_getApEnable(ssidIndex,&output_bool);
3462 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3463
3464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3465 return RETURN_OK;
3466}
3467
3468// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3469INT wifi_getSSIDName(INT apIndex, CHAR *output)
3470{
3471 char config_file[MAX_BUF_SIZE] = {0};
3472
3473 if (NULL == output)
3474 return RETURN_ERR;
3475
3476 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3477 wifi_hostapdRead(config_file,"ssid",output,32);
3478
3479 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3480 return RETURN_OK;
3481}
3482
3483// Set a max 32 byte string and sets an internal variable to the SSID name
3484INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3485{
3486 char str[MAX_BUF_SIZE]={'\0'};
3487 char cmd[MAX_CMD_SIZE]={'\0'};
3488 struct params params;
3489 char config_file[MAX_BUF_SIZE] = {0};
3490
3491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3492 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3493 return RETURN_ERR;
3494
3495 params.name = "ssid";
3496 params.value = ssid_string;
3497 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3498 wifi_hostapdWrite(config_file, &params, 1);
3499 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3501
3502 return RETURN_OK;
3503}
3504
3505//Get the BSSID
3506INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3507{
3508 char cmd[MAX_CMD_SIZE]="";
3509
3510 if (NULL == output_string)
3511 return RETURN_ERR;
3512
3513 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3514 {
3515 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3516 _syscmd(cmd, output_string, 64);
3517 return RETURN_OK;
3518 }
3519 strncpy(output_string, "\0", 1);
3520
3521 return RETURN_ERR;
3522}
3523
3524//Get the MAC address associated with this Wifi SSID
3525INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3526{
3527 wifi_getBaseBSSID(ssidIndex,output_string);
3528 return RETURN_OK;
3529}
3530
3531//Get the basic SSID traffic static info
3532//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3533//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3534INT wifi_applySSIDSettings(INT ssidIndex)
3535{
3536 BOOL status = false;
3537 char cmd[MAX_CMD_SIZE] = {0};
3538 char buf[MAX_CMD_SIZE] = {0};
3539 int apIndex, ret;
3540 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3541
3542 wifi_getApEnable(ssidIndex,&status);
3543 // Do not apply when ssid index is disabled
3544 if (status == false)
3545 return RETURN_OK;
3546
3547 /* Doing full remove and add for ssid Index
3548 * Not all hostapd options are supported with reload
3549 * for example macaddr_acl
3550 */
3551 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3552 return RETURN_ERR;
3553
3554 ret = wifi_setApEnable(ssidIndex,true);
3555
3556 /* Workaround for hostapd issue with multiple bss definitions
3557 * when first created interface will be removed
3558 * then all vaps other vaps on same phy are removed
3559 * after calling setApEnable to false readd all enabled vaps */
3560 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3561 apIndex = 2*i+radioIndex;
3562 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3563 _syscmd(cmd, buf, sizeof(buf));
3564 if(*buf == '1')
3565 wifi_setApEnable(apIndex, true);
3566 }
3567
3568 return ret;
3569}
3570
developera3c68b92022-09-13 15:27:29 +08003571struct channels_noise {
3572 int channel;
3573 int noise;
3574};
3575
3576// Return noise array for each channel
3577int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3578{
3579 FILE *f = NULL;
3580 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003581 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003582 size_t len = 0;
3583 ssize_t read = 0;
3584 int tmp = 0, arr_index = -1;
3585
3586 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3587
3588 if ((f = popen(cmd, "r")) == NULL) {
3589 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3590 return RETURN_ERR;
3591 }
developer5550e242022-09-30 09:59:32 +08003592
3593 while(fgets(line, sizeof(line), f) != NULL) {
3594 if(arr_index < channels_num){
3595 sscanf(line, "%d", &tmp);
3596 if (tmp > 0) { // channel frequency, the first line must be frequency
3597 arr_index++;
3598 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3599 } else { // noise
3600 channels_noise_arr[arr_index].noise = tmp;
3601 }
3602 }else{
3603 break;
developera3c68b92022-09-13 15:27:29 +08003604 }
3605 }
developera3c68b92022-09-13 15:27:29 +08003606 pclose(f);
3607 return RETURN_OK;
3608}
3609
developer06a01d92022-09-07 16:32:39 +08003610//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3611//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3612INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3613{
developera3c68b92022-09-13 15:27:29 +08003614 int index = -1;
3615 wifi_neighbor_ap2_t *scan_array = NULL;
3616 char cmd[256]={0};
3617 char buf[128]={0};
3618 char file_name[32] = {0};
3619 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003620 char line[256] = {0};
3621 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003622 int freq=0;
3623 FILE *f = NULL;
3624 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003625 int channels_num = 0;
3626 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003627 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003628 bool filter_enable = false;
3629 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003630
developer615510b2022-09-27 10:14:35 +08003631 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003632
3633 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3634 f = fopen(file_name, "r");
3635 if (f != NULL) {
3636 fgets(filter_SSID, sizeof(file_name), f);
3637 if (strlen(filter_SSID) != 0)
3638 filter_enable = true;
3639 fclose(f);
3640 }
3641
3642 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003643 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003644 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003645
developer5550e242022-09-30 09:59:32 +08003646
developer06a01d92022-09-07 16:32:39 +08003647
developera3c68b92022-09-13 15:27:29 +08003648 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 +08003649 // 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 +08003650 fprintf(stderr, "cmd: %s\n", cmd);
3651 if ((f = popen(cmd, "r")) == NULL) {
3652 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3653 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003654 }
developer5550e242022-09-30 09:59:32 +08003655
3656 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3657 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3658
developer615510b2022-09-27 10:14:35 +08003659 ret = fgets(line, sizeof(line), f);
3660 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003661 if(strstr(line, "BSS") != NULL) { // new neighbor info
3662 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3663 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3664 // 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 +08003665
developera3c68b92022-09-13 15:27:29 +08003666 if (!filter_BSS) {
3667 index++;
3668 wifi_neighbor_ap2_t *tmp;
3669 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3670 if (tmp == NULL) { // no more memory to use
3671 index--;
3672 wifi_dbg_printf("%s: realloc failed\n", __func__);
3673 break;
3674 }
3675 scan_array = tmp;
3676 }
3677 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3678
3679 filter_BSS = false;
3680 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3681 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3682 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3683 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3684 } else if (strstr(line, "freq") != NULL) {
3685 sscanf(line," freq: %d", &freq);
3686 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3687
3688 if (freq >= 2412 && freq <= 2484) {
3689 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3690 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3691 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3692 }
3693 else if (freq >= 5160 && freq <= 5805) {
3694 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3695 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3696 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3697 }
3698
3699 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003700 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003701 for (int i = 0; i < channels_num; i++) {
3702 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3703 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3704 break;
3705 }
3706 }
3707 }
3708 } else if (strstr(line, "beacon interval") != NULL) {
3709 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3710 } else if (strstr(line, "signal") != NULL) {
3711 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3712 } else if (strstr(line,"SSID") != NULL) {
3713 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3714 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3715 filter_BSS = true;
3716 }
3717 } else if (strstr(line, "Supported rates") != NULL) {
3718 char SRate[80] = {0}, *tmp = NULL;
3719 memset(buf, 0, sizeof(buf));
3720 strcpy(SRate, line);
3721 tmp = strtok(SRate, ":");
3722 tmp = strtok(NULL, ":");
3723 strcpy(buf, tmp);
3724 memset(SRate, 0, sizeof(SRate));
3725
3726 tmp = strtok(buf, " \n");
3727 while (tmp != NULL) {
3728 strcat(SRate, tmp);
3729 if (SRate[strlen(SRate) - 1] == '*') {
3730 SRate[strlen(SRate) - 1] = '\0';
3731 }
3732 strcat(SRate, ",");
3733
3734 tmp = strtok(NULL, " \n");
3735 }
3736 SRate[strlen(SRate) - 1] = '\0';
3737 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3738 } else if (strstr(line, "DTIM") != NULL) {
3739 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3740 } else if (strstr(line, "VHT capabilities") != NULL) {
3741 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3742 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3743 } else if (strstr(line, "HT capabilities") != NULL) {
3744 strcat(scan_array[index].ap_SupportedStandards, ",n");
3745 strcpy(scan_array[index].ap_OperatingStandards, "n");
3746 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003747 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003748 sscanf(line," * channel width: %d", &vht_channel_width);
3749 if(vht_channel_width == 1) {
3750 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3751 } else {
3752 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3753 }
3754 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3755 continue;
3756 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003757 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003758 sscanf(line," * secondary channel offset: %s", &buf);
3759 if (!strcmp(buf, "above")) {
3760 //40Mhz +
3761 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3762 }
3763 else if (!strcmp(buf, "below")) {
3764 //40Mhz -
3765 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3766 } else {
3767 //20Mhz
3768 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3769 }
3770 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3771 continue;
3772 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003773 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3774 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3775 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003776 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3777 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003778 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003779 else
developer615510b2022-09-27 10:14:35 +08003780 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003781 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003782 if (strstr(line, "HE80/5GHz") != NULL) {
3783 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3784 ret = fgets(line, sizeof(line), f);
3785 } else
3786 continue;
developera3c68b92022-09-13 15:27:29 +08003787 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003788 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003789 }
developer615510b2022-09-27 10:14:35 +08003790 continue;
developera3c68b92022-09-13 15:27:29 +08003791 } else if (strstr(line, "WPA") != NULL) {
3792 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3793 } else if (strstr(line, "RSN") != NULL) {
3794 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3795 } else if (strstr(line, "Group cipher") != NULL) {
3796 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3797 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3798 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3799 }
3800 }
developer615510b2022-09-27 10:14:35 +08003801 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003802 }
3803
3804 if (!filter_BSS) {
3805 *output_array_size = index + 1;
3806 } else {
3807 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3808 *output_array_size = index;
3809 }
3810 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003811 pclose(f);
developer5550e242022-09-30 09:59:32 +08003812 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003813 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003814 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003815}
3816
3817//>> Deprecated: used for old RDKB code.
3818INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3819{
3820 INT status = RETURN_ERR;
3821
3822 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3823 output_struct->wifi_PLCPErrorCount = 0;
3824 output_struct->wifi_FCSErrorCount = 0;
3825 output_struct->wifi_InvalidMACCount = 0;
3826 output_struct->wifi_PacketsOtherReceived = 0;
3827 output_struct->wifi_Noise = 0;
3828 status = RETURN_OK;
3829 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3830 return status;
3831}
3832
3833INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3834{
3835 char cmd[128];
3836 char buf[1280];
3837 char *pos = NULL;
3838
3839 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3840 if (NULL == output_struct)
3841 return RETURN_ERR;
3842
3843 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3844
3845 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3846 _syscmd(cmd, buf, sizeof(buf));
3847
3848 pos = buf;
3849 if ((pos = strstr(pos, "RX packets:")) == NULL)
3850 return RETURN_ERR;
3851 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3852
3853 if ((pos = strstr(pos, "TX packets:")) == NULL)
3854 return RETURN_ERR;
3855 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3856
3857 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3858 return RETURN_ERR;
3859 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3860
3861 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3862 return RETURN_ERR;
3863 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3864
3865 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3866 _syscmd(cmd, buf, sizeof(buf));
3867 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3868
3869#if 0
3870 //TODO: need to revisit below implementation
3871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3872 char interface_name[MAX_BUF_SIZE] = {0};
3873 char interface_status[MAX_BUF_SIZE] = {0};
3874 char Value[MAX_BUF_SIZE] = {0};
3875 char buf[MAX_CMD_SIZE] = {0};
3876 char cmd[MAX_CMD_SIZE] = {0};
3877 FILE *fp = NULL;
3878
3879 if (NULL == output_struct) {
3880 return RETURN_ERR;
3881 }
3882
3883 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3884
3885 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3886 {
3887 if(apIndex == 0) //private_wifi for 2.4G
3888 {
3889 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3890 }
3891 else if(apIndex == 1) //private_wifi for 5G
3892 {
3893 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3894 }
3895 else if(apIndex == 4) //public_wifi for 2.4G
3896 {
3897 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3898 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3899 {
3900 return RETURN_ERR;
3901 }
3902 if(buf[0] == '#')//tp-link
3903 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3904 else//tenda
3905 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3906 }
3907 else if(apIndex == 5) //public_wifi for 5G
3908 {
3909 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3910 }
3911
3912 GetIfacestatus(interface_name, interface_status);
3913
3914 if(0 != strcmp(interface_status, "1"))
3915 return RETURN_ERR;
3916
3917 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3918 system(cmd);
3919
3920 fp = fopen("/tmp/SSID_Stats.txt", "r");
3921 if(fp == NULL)
3922 {
3923 printf("/tmp/SSID_Stats.txt not exists \n");
3924 return RETURN_ERR;
3925 }
3926 fclose(fp);
3927
3928 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3929 File_Reading(buf, Value);
3930 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3931
3932 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3933 File_Reading(buf, Value);
3934 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3935
3936 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3937 File_Reading(buf, Value);
3938 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3939
3940 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3941 File_Reading(buf, Value);
3942 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3943
3944 /* There is no specific parameter from caller to associate the value wifi_Associations */
3945 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3946 //_syscmd(cmd, buf, sizeof(buf));
3947 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3948 }
3949#endif
3950 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3951 return RETURN_OK;
3952}
3953
3954INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3955{
3956 char interface_name[MAX_BUF_SIZE] = {0};
3957 char interface_status[MAX_BUF_SIZE] = {0};
3958 char Value[MAX_BUF_SIZE] = {0};
3959 char buf[MAX_CMD_SIZE] = {0};
3960 char cmd[MAX_CMD_SIZE] = {0};
3961 FILE *fp = NULL;
3962
3963 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3964 if (NULL == output_struct)
3965 return RETURN_ERR;
3966
3967 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3968
3969 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3970 {
3971 if(apIndex == 0) //private_wifi for 2.4G
3972 {
3973 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3974 }
3975 else if(apIndex == 1) //private_wifi for 5G
3976 {
3977 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3978 }
3979 else if(apIndex == 4) //public_wifi for 2.4G
3980 {
3981 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3982 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3983 {
3984 return RETURN_ERR;
3985 }
3986 if(buf[0] == '#')
3987 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3988 else
3989 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3990 }
3991 else if(apIndex == 5) //public_wifi for 5G
3992 {
3993 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3994 }
3995
3996 GetIfacestatus(interface_name, interface_status);
3997
3998 if(0 != strcmp(interface_status, "1"))
3999 return RETURN_ERR;
4000
4001 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4002 system(cmd);
4003
4004 fp = fopen("/tmp/SSID_Stats.txt", "r");
4005 if(fp == NULL)
4006 {
4007 printf("/tmp/SSID_Stats.txt not exists \n");
4008 return RETURN_ERR;
4009 }
4010 fclose(fp);
4011
4012 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4013 File_Reading(buf, Value);
4014 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4015
4016 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4017 File_Reading(buf, Value);
4018 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4019
4020 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4021 File_Reading(buf, Value);
4022 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4023
4024 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4025 File_Reading(buf, Value);
4026 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4027 }
4028
4029 output_struct->wifi_UnicastPacketsSent = 0;
4030 output_struct->wifi_UnicastPacketsReceived = 0;
4031 output_struct->wifi_MulticastPacketsSent = 0;
4032 output_struct->wifi_MulticastPacketsReceived = 0;
4033 output_struct->wifi_BroadcastPacketsSent = 0;
4034 output_struct->wifi_BroadcastPacketsRecevied = 0;
4035 output_struct->wifi_UnknownPacketsReceived = 0;
4036
4037 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4038 return RETURN_OK;
4039}
4040
4041INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4042{
4043 INT status = RETURN_ERR;
4044
4045 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4046 //Below values should get updated from hal
4047 output_struct->wifi_RetransCount=0;
4048 output_struct->wifi_FailedRetransCount=0;
4049 output_struct->wifi_RetryCount=0;
4050 output_struct->wifi_MultipleRetryCount=0;
4051 output_struct->wifi_ACKFailureCount=0;
4052 output_struct->wifi_AggregatedPacketCount=0;
4053
4054 status = RETURN_OK;
4055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4056
4057 return status;
4058}
4059
4060INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4061{
4062 INT status = RETURN_ERR;
4063 UINT index;
4064 wifi_neighbor_ap_t *pt=NULL;
4065
4066 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4067 *output_array_size=2;
4068 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4069 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4070 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4071 strcpy(pt->ap_Radio,"");
4072 strcpy(pt->ap_SSID,"");
4073 strcpy(pt->ap_BSSID,"");
4074 strcpy(pt->ap_Mode,"");
4075 pt->ap_Channel=1;
4076 pt->ap_SignalStrength=0;
4077 strcpy(pt->ap_SecurityModeEnabled,"");
4078 strcpy(pt->ap_EncryptionMode,"");
4079 strcpy(pt->ap_OperatingFrequencyBand,"");
4080 strcpy(pt->ap_SupportedStandards,"");
4081 strcpy(pt->ap_OperatingStandards,"");
4082 strcpy(pt->ap_OperatingChannelBandwidth,"");
4083 pt->ap_BeaconPeriod=1;
4084 pt->ap_Noise=0;
4085 strcpy(pt->ap_BasicDataTransferRates,"");
4086 strcpy(pt->ap_SupportedDataTransferRates,"");
4087 pt->ap_DTIMPeriod=1;
4088 pt->ap_ChannelUtilization = 1;
4089 }
4090
4091 status = RETURN_OK;
4092 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4093
4094 return status;
4095}
4096
4097//----------------- AP HAL -------------------------------
4098
4099//>> Deprecated: used for old RDKB code.
4100INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4101{
4102 if (NULL == output_ulong || NULL == output_struct)
4103 return RETURN_ERR;
4104 *output_ulong = 0;
4105 *output_struct = NULL;
4106 return RETURN_OK;
4107}
4108
4109#ifdef HAL_NETLINK_IMPL
4110static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4111 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4112 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4113 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4114 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4115 char mac_addr[20];
4116 static int count=0;
4117 int rate=0;
4118
4119 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4120
4121 nla_parse(tb,
4122 NL80211_ATTR_MAX,
4123 genlmsg_attrdata(gnlh, 0),
4124 genlmsg_attrlen(gnlh, 0),
4125 NULL);
4126
4127 if(!tb[NL80211_ATTR_STA_INFO]) {
4128 fprintf(stderr, "sta stats missing!\n");
4129 return NL_SKIP;
4130 }
4131
4132
4133 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4134 fprintf(stderr, "failed to parse nested attributes!\n");
4135 return NL_SKIP;
4136 }
4137
4138 //devIndex starts from 1
4139 if( ++count == out->wifi_devIndex )
4140 {
4141 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4142 //Getting the mac addrress
4143 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4144
4145 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4146 fprintf(stderr, "failed to parse nested rate attributes!");
4147 return NL_SKIP;
4148 }
4149
4150 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4151 if(rinfo[NL80211_RATE_INFO_BITRATE])
4152 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4153 out->wifi_devTxRate = rate/10;
4154 }
4155
4156 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4157 fprintf(stderr, "failed to parse nested rate attributes!");
4158 return NL_SKIP;
4159 }
4160
4161 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4162 if(rinfo[NL80211_RATE_INFO_BITRATE])
4163 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4164 out->wifi_devRxRate = rate/10;
4165 }
4166 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4167 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4168
4169 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4170 count = 0; //starts the count for next cycle
4171 return NL_STOP;
4172 }
4173
4174 return NL_SKIP;
4175
4176}
4177#endif
4178
4179INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4180{
4181#ifdef HAL_NETLINK_IMPL
4182 Netlink nl;
4183 char if_name[10];
4184
4185 wifi_device_info_t info;
4186 info.wifi_devIndex = devIndex;
4187
4188 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4189
4190 nl.id = initSock80211(&nl);
4191
4192 if (nl.id < 0) {
4193 fprintf(stderr, "Error initializing netlink \n");
4194 return -1;
4195 }
4196
4197 struct nl_msg* msg = nlmsg_alloc();
4198
4199 if (!msg) {
4200 fprintf(stderr, "Failed to allocate netlink message.\n");
4201 nlfree(&nl);
4202 return -2;
4203 }
4204
4205 genlmsg_put(msg,
4206 NL_AUTO_PORT,
4207 NL_AUTO_SEQ,
4208 nl.id,
4209 0,
4210 NLM_F_DUMP,
4211 NL80211_CMD_GET_STATION,
4212 0);
4213
4214 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4215 nl_send_auto(nl.socket, msg);
4216 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4217 nl_recvmsgs(nl.socket, nl.cb);
4218 nlmsg_free(msg);
4219 nlfree(&nl);
4220
4221 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4222 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4223 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4224 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4225 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4226 return RETURN_OK;
4227#else
4228 //iw utility to retrieve station information
4229#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4230#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4231#define MACFILE "/tmp/wifi_AssoMac.txt"
4232#define TXRATEFILE "/tmp/wifi_txrate.txt"
4233#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4234 FILE *file = NULL;
4235 char if_name[10] = {'\0'};
4236 char pipeCmd[256] = {'\0'};
4237 char line[256];
4238 int count,device = 0;
4239
4240 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4241
4242 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4243 file = popen(pipeCmd, "r");
4244
4245 if(file == NULL)
4246 return RETURN_ERR; //popen failed
4247
4248 fgets(line, sizeof line, file);
4249 device = atoi(line);
4250 pclose(file);
4251
4252 if(device == 0)
4253 return RETURN_ERR; //No devices are connected
4254
4255 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4256 system(pipeCmd);
4257
4258 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4259
4260 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4261
4262 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4263
4264 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4265
4266 //devIndex starts from 1, ++count
4267 if((file = fopen(SIGNALFILE, "r")) != NULL )
4268 {
4269 for(count =0;fgets(line, sizeof line, file) != NULL;)
4270 {
4271 if (++count == devIndex)
4272 {
4273 output_struct->wifi_devSignalStrength = atoi(line);
4274 break;
4275 }
4276 }
4277 fclose(file);
4278 }
4279 else
4280 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4281
4282 if((file = fopen(MACFILE, "r")) != NULL )
4283 {
4284 for(count =0;fgets(line, sizeof line, file) != NULL;)
4285 {
4286 if (++count == devIndex)
4287 {
4288 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]);
4289 break;
4290 }
4291 }
4292 fclose(file);
4293 }
4294 else
4295 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4296
4297 if((file = fopen(TXRATEFILE, "r")) != NULL )
4298 {
4299 for(count =0;fgets(line, sizeof line, file) != NULL;)
4300 {
4301 if (++count == devIndex)
4302 {
4303 output_struct->wifi_devTxRate = atoi(line);
4304 break;
4305 }
4306 }
4307 fclose(file);
4308 }
4309 else
4310 fprintf(stderr,"fopen wifi_txrate.txt failed");
4311
4312 if((file = fopen(RXRATEFILE, "r")) != NULL)
4313 {
4314 for(count =0;fgets(line, sizeof line, file) != NULL;)
4315 {
4316 if (++count == devIndex)
4317 {
4318 output_struct->wifi_devRxRate = atoi(line);
4319 break;
4320 }
4321 }
4322 fclose(file);
4323 }
4324 else
4325 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4326
4327 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4328
4329 return RETURN_OK;
4330#endif
4331}
4332
4333INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4334{
4335 if (NULL == device)
4336 return RETURN_ERR;
4337 return RETURN_OK;
4338}
4339//<<
4340
4341
4342//--------------wifi_ap_hal-----------------------------
4343//enables CTS protection for the radio used by this AP
4344INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4345{
4346 //save config and Apply instantly
4347 return RETURN_ERR;
4348}
4349
4350// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4351INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4352{
developer463d39a2022-09-13 15:32:51 +08004353 char config_file[64] = {'\0'};
4354 char buf[64] = {'\0'};
4355 struct params list;
4356
4357 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4358 list.name = "ht_coex";
4359 snprintf(buf, sizeof(buf), "%d", enable);
4360 list.value = buf;
4361
4362 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4363 wifi_hostapdWrite(config_file, &list, 1);
4364 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4365
4366 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4367
4368 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004369}
4370
4371//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4372INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4373{
developerea4bcce2022-09-13 15:26:13 +08004374 char config_file[MAX_BUF_SIZE] = {'\0'};
4375 char buf[MAX_BUF_SIZE] = {'\0'};
4376 struct params list;
4377
4378 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4379 if (threshold < 256 || threshold > 2346 )
4380 return RETURN_ERR;
4381 list.name = "fragm_threshold";
4382 snprintf(buf, sizeof(buf), "%d", threshold);
4383 list.value = buf;
4384
4385 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4386 wifi_hostapdWrite(config_file, &list, 1);
4387 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004388
developerea4bcce2022-09-13 15:26:13 +08004389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004390
4391 return RETURN_OK;
4392}
4393
4394// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4395INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4396{
developer51a927d2022-09-13 15:42:22 +08004397 char config_file[64] = {'\0'};
4398 char cmd[128] = {'\0'};
4399 char buf[64] = {'\0'};
4400 char stbc_config[16] = {'\0'};
4401 wifi_band band;
4402 int iterator = 0;
4403 BOOL current_stbc = FALSE;
4404
4405 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4406
4407 band = wifi_index_to_band(radioIndex);
4408 if (band == band_invalid)
4409 return RETURN_ERR;
4410
4411 if (band == band_2_4)
4412 iterator = 1;
4413 else if (band == band_5)
4414 iterator = 2;
4415 else
4416 return RETURN_OK;
4417
4418 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4419
4420 // set ht and vht config
4421 for (int i = 0; i < iterator; i++) {
4422 memset(stbc_config, 0, sizeof(stbc_config));
4423 memset(cmd, 0, sizeof(cmd));
4424 memset(buf, 0, sizeof(buf));
4425 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4426 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4427 _syscmd(cmd, buf, sizeof(buf));
4428 if (strlen(buf) != 0)
4429 current_stbc = TRUE;
4430 if (current_stbc == STBC_Enable)
4431 continue;
4432
4433 if (STBC_Enable == TRUE) {
4434 // Append the STBC flags in capab config
4435 memset(cmd, 0, sizeof(cmd));
4436 if (i == 0)
4437 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4438 else
4439 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4440 _syscmd(cmd, buf, sizeof(buf));
4441 } else if (STBC_Enable == FALSE) {
4442 // Remove the STBC flags and remain other flags in capab
4443 memset(cmd, 0, sizeof(cmd));
4444 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4445 _syscmd(cmd, buf, sizeof(buf));
4446 memset(cmd, 0, sizeof(cmd));
4447 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4448 _syscmd(cmd, buf, sizeof(buf));
4449 }
4450 }
4451
4452 wifi_reloadAp(radioIndex);
4453
4454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4455 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004456}
4457
4458// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4459INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4460{
developer54e6b9f2022-09-28 14:41:20 +08004461 char AMSDU_file_path[64] = {0};
4462
4463 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4464
4465 if(output_bool == NULL)
4466 return RETURN_ERR;
4467
4468 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4469
4470 if (access(AMSDU_file_path, F_OK) == 0)
4471 *output_bool = TRUE;
4472 else
4473 *output_bool = FALSE;
4474
4475 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4476 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004477}
4478
4479// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4480INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4481{
developer54e6b9f2022-09-28 14:41:20 +08004482 char cmd[64]={0};
4483 char buf[64]={0};
4484 char AMSDU_file_path[64] = {0};
4485
4486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4487
4488 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4489 _syscmd(cmd, buf, sizeof(buf));
4490
4491 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4492 memset(cmd, 0, sizeof(cmd));
4493 if (amsduEnable == TRUE)
4494 sprintf(cmd, "touch %s", AMSDU_file_path);
4495 else
4496 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4497 _syscmd(cmd, buf, sizeof(buf));
4498
4499 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4500 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004501}
4502
4503//P2 // outputs the number of Tx streams
4504INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4505{
developer2de97692022-09-26 14:00:03 +08004506 char buf[8] = {0};
4507 char cmd[128] = {0};
4508
4509 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4510
4511 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4512 _syscmd(cmd, buf, sizeof(buf));
4513
4514 // if there is no record, output the max number of spatial streams
4515 if (strlen(buf) == 0) {
4516 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4517 _syscmd(cmd, buf, sizeof(buf));
4518 }
4519
4520 *output_int = (INT)strtol(buf, NULL, 10);
4521
4522 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4523
4524 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004525}
4526
4527//P2 // sets the number of Tx streams to an enviornment variable
4528INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4529{
developer2de97692022-09-26 14:00:03 +08004530 char cmd[128] = {0};
4531 char buf[128] = {0};
4532 char chain_mask_file[128] = {0};
4533 FILE *f = NULL;
4534
4535 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4536
4537 if (numStreams == 0) {
4538 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4539 return RETURN_ERR;
4540 }
4541 wifi_setRadioEnable(radioIndex, FALSE);
4542 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4543 _syscmd(cmd, buf, sizeof(buf));
4544
4545 if (strlen(buf) > 0) {
4546 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4547 return RETURN_ERR;
4548 }
4549 wifi_setRadioEnable(radioIndex, TRUE);
4550
4551 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4552 f = fopen(chain_mask_file, "w");
4553 if (f == NULL) {
4554 fprintf(stderr, "%s: fopen failed.\n", __func__);
4555 return RETURN_ERR;
4556 }
4557 fprintf(f, "%d", numStreams);
4558 fclose(f);
4559 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4560 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004561}
4562
4563//P2 // outputs the number of Rx streams
4564INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4565{
developer2de97692022-09-26 14:00:03 +08004566 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4567 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4568 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004569 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004570 }
4571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004572 return RETURN_OK;
4573}
4574
4575//P2 // sets the number of Rx streams to an enviornment variable
4576INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4577{
developer2de97692022-09-26 14:00:03 +08004578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4579 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4580 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4581 return RETURN_ERR;
4582 }
4583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004584 return RETURN_ERR;
4585}
4586
4587//Get radio RDG enable setting
4588INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4589{
4590 if (NULL == output_bool)
4591 return RETURN_ERR;
4592 *output_bool = TRUE;
4593 return RETURN_OK;
4594}
4595
4596//Get radio RDG enable setting
4597INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4598{
4599 if (NULL == output_bool)
4600 return RETURN_ERR;
4601 *output_bool = TRUE;
4602 return RETURN_OK;
4603}
4604
4605//Set radio RDG enable setting
4606INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4607{
4608 return RETURN_ERR;
4609}
4610
4611//Get radio ADDBA enable setting
4612INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4613{
4614 if (NULL == output_bool)
4615 return RETURN_ERR;
4616 *output_bool = TRUE;
4617 return RETURN_OK;
4618}
4619
4620//Set radio ADDBA enable setting
4621INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4622{
4623 return RETURN_ERR;
4624}
4625
4626//Get radio auto block ack enable setting
4627INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4628{
4629 if (NULL == output_bool)
4630 return RETURN_ERR;
4631 *output_bool = TRUE;
4632 return RETURN_OK;
4633}
4634
4635//Set radio auto block ack enable setting
4636INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4637{
4638 return RETURN_ERR;
4639}
4640
4641//Get radio 11n pure mode enable support
4642INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4643{
4644 if (NULL == output_bool)
4645 return RETURN_ERR;
4646 *output_bool = TRUE;
4647 return RETURN_OK;
4648}
4649
4650//Get radio 11n pure mode enable setting
4651INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4652{
4653 if (NULL == output_bool)
4654 return RETURN_ERR;
4655 *output_bool = TRUE;
4656 return RETURN_OK;
4657}
4658
4659//Set radio 11n pure mode enable setting
4660INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4661{
4662 return RETURN_ERR;
4663}
4664
4665//Get radio IGMP snooping enable setting
4666INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4667{
developer81bf2ed2022-09-13 15:31:14 +08004668 char cmd[128]={0};
4669 char buf[4]={0};
4670 bool bridge = FALSE, mac80211 = FALSE;
4671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4672
4673 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004674 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004675
4676 *output_bool = FALSE;
4677
4678 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4679 _syscmd(cmd, buf, sizeof(buf));
4680 if (strncmp(buf, "1", 1) == 0)
4681 bridge = TRUE;
4682
4683 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4684 _syscmd(cmd, buf, sizeof(buf));
4685 if (strncmp(buf, "1", 1) == 0)
4686 mac80211 = TRUE;
4687
4688 if (bridge && mac80211)
4689 *output_bool = TRUE;
4690
4691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004692 return RETURN_OK;
4693}
4694
4695//Set radio IGMP snooping enable setting
4696INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4697{
developer81bf2ed2022-09-13 15:31:14 +08004698 char cmd[128]={0};
4699 char buf[4]={0};
4700
4701 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4702
4703 // bridge
4704 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4705 _syscmd(cmd, buf, sizeof(buf));
4706
4707 // mac80211
4708 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4709 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4710 _syscmd(cmd, buf, sizeof(buf));
4711 }
4712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4713 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004714}
4715
4716//Get the Reset count of radio
4717INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4718{
4719 if (NULL == output_int)
4720 return RETURN_ERR;
4721 *output_int = (radioIndex==0)? 1: 3;
4722
4723 return RETURN_OK;
4724}
4725
4726
4727//---------------------------------------------------------------------------------------------------
4728//
4729// Additional Wifi AP level APIs used for Access Point devices
4730//
4731//---------------------------------------------------------------------------------------------------
4732
4733// creates a new ap and pushes these parameters to the hardware
4734INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4735{
4736 char buf[1024];
4737 char cmd[128];
4738
4739 if (NULL == essid)
4740 return RETURN_ERR;
4741
4742 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4743 _syscmd(cmd, buf, sizeof(buf));
4744
4745 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4746 _syscmd(cmd, buf, sizeof(buf));
4747
4748 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4749
4750 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4751 _syscmd(cmd, buf, sizeof(buf));
4752
4753 return RETURN_OK;
4754}
4755
4756// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4757INT wifi_deleteAp(INT apIndex)
4758{
4759 char buf[1024];
4760 char cmd[128];
4761
4762 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4763 _syscmd(cmd, buf, sizeof(buf));
4764
4765 wifi_removeApSecVaribles(apIndex);
4766
4767 return RETURN_OK;
4768}
4769
4770// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4771INT wifi_getApName(INT apIndex, CHAR *output_string)
4772{
4773 if(NULL == output_string)
4774 return RETURN_ERR;
4775
4776 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4777 return RETURN_OK;
4778}
4779
4780// Outputs the index number in that corresponds to the SSID string
4781INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4782{
4783 CHAR *pos = NULL;
4784
4785 *output_int = -1;
4786 pos = strstr(inputSsidString, AP_PREFIX);
4787 if(pos)
4788 {
4789 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4790 return RETURN_OK;
4791 }
4792 return RETURN_ERR;
4793}
4794
4795INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4796{
4797 return wifi_getIndexFromName(inputSsidString, output_int);
4798}
4799
4800// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4801INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4802{
4803 char buf[MAX_BUF_SIZE] = {0};
4804 char cmd[MAX_CMD_SIZE] = {0};
4805 char config_file[MAX_BUF_SIZE] = {0};
4806
4807 if(NULL == output_string)
4808 return RETURN_ERR;
4809
4810 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4811 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4812 if((strcmp(buf,"3")==0))
4813 snprintf(output_string, 32, "WPAand11i");
4814 else if((strcmp(buf,"2")==0))
4815 snprintf(output_string, 32, "11i");
4816 else if((strcmp(buf,"1")==0))
4817 snprintf(output_string, 32, "WPA");
4818 else
4819 snprintf(output_string, 32, "None");
4820
4821 return RETURN_OK;
4822}
4823
4824// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4825INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4826{
4827 char config_file[MAX_BUF_SIZE] = {0};
4828 struct params list;
4829
4830 if (NULL == beaconTypeString)
4831 return RETURN_ERR;
4832 list.name = "wpa";
4833 list.value = "0";
4834
4835 if((strcmp(beaconTypeString,"WPAand11i")==0))
4836 list.value="3";
4837 else if((strcmp(beaconTypeString,"11i")==0))
4838 list.value="2";
4839 else if((strcmp(beaconTypeString,"WPA")==0))
4840 list.value="1";
4841
4842 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4843 wifi_hostapdWrite(config_file, &list, 1);
4844 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4845 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4846 return RETURN_OK;
4847}
4848
4849// sets the beacon interval on the hardware for this AP
4850INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4851{
developer5f222492022-09-13 15:21:52 +08004852 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4853 struct params params={'\0'};
4854 char buf[MAX_BUF_SIZE] = {'\0'};
4855 char config_file[MAX_BUF_SIZE] = {'\0'};
4856
4857 params.name = "beacon_int";
4858 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4859 params.value = buf;
4860
4861 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4862 wifi_hostapdWrite(config_file, &params, 1);
4863
4864 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4866 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004867}
4868
4869INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4870{
4871 //save config and apply instantly
4872 return RETURN_ERR;
4873}
4874
4875// Get the packet size threshold supported.
4876INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4877{
4878 //save config and apply instantly
4879 if (NULL == output_bool)
4880 return RETURN_ERR;
4881 *output_bool = FALSE;
4882 return RETURN_OK;
4883}
4884
4885// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4886INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4887{
4888 char cmd[128];
4889 char buf[512];
4890
4891 if (threshold > 0)
4892 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4893 else
4894 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4895 _syscmd(cmd, buf, sizeof(buf));
4896
4897 return RETURN_OK;
4898}
4899
4900// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4901INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4902{
4903 if (NULL == output_string)
4904 return RETURN_ERR;
4905 snprintf(output_string, 32, "TKIPandAESEncryption");
4906 return RETURN_OK;
4907
4908}
4909
4910// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4911INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4912{
4913 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4914 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4915
4916 if(NULL == output_string)
4917 return RETURN_ERR;
4918
4919 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4920 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4921
4922 if(strcmp(buf,"0")==0)
4923 {
4924 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4925 snprintf(output_string, 32, "None");
4926 return RETURN_OK;
4927 }
4928 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4929 param_name = "rsn_pairwise";
4930 else if((strcmp(buf,"1")==0))
4931 param_name = "wpa_pairwise";
4932 else
4933 return RETURN_ERR;
4934 memset(output_string,'\0',32);
4935 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4936 wifi_hostapdRead(config_file,param_name,output_string,32);
4937 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4938
4939 if(strcmp(output_string,"TKIP") == 0)
4940 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4941 else if(strcmp(output_string,"CCMP") == 0)
4942 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4943 else if(strcmp(output_string,"TKIP CCMP") == 0)
4944 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4945
4946 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4947 return RETURN_OK;
4948}
4949
4950// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4951INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4952{
4953 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4954 struct params params={'\0'};
4955 char output_string[32];
4956 char config_file[MAX_BUF_SIZE] = {0};
4957
4958 memset(output_string,'\0',32);
4959 wifi_getApWpaEncryptionMode(apIndex,output_string);
4960
4961 if(strcmp(encMode, "TKIPEncryption") == 0)
4962 params.value = "TKIP";
4963 else if(strcmp(encMode,"AESEncryption") == 0)
4964 params.value = "CCMP";
4965 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4966 params.value = "TKIP CCMP";
4967
4968 if((strcmp(output_string,"WPAand11i")==0))
4969 {
4970 params.name = "wpa_pairwise";
4971 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4972 wifi_hostapdWrite(config_file, &params, 1);
4973 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4974
4975 params.name,"rsn_pairwise";
4976 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4977 wifi_hostapdWrite(config_file, &params, 1);
4978 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4979
4980 return RETURN_OK;
4981 }
4982 else if((strcmp(output_string,"11i")==0))
4983 {
4984 params.name = "rsn_pairwise";
4985 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4986 wifi_hostapdWrite(config_file, &params, 1);
4987 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4988 return RETURN_OK;
4989 }
4990 else if((strcmp(output_string,"WPA")==0))
4991 {
4992 params.name = "wpa_pairwise";
4993 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4994 wifi_hostapdWrite(config_file, &params, 1);
4995 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4996 return RETURN_OK;
4997 }
4998
4999 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5000 return RETURN_OK;
5001}
5002
5003// deletes internal security varable settings for this ap
5004INT wifi_removeApSecVaribles(INT apIndex)
5005{
5006 //TODO: remove the entry in hostapd config file
5007 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5008 //_syscmd(cmd, buf, sizeof(buf));
5009
5010 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5011 //_syscmd(cmd, buf, sizeof(buf));
5012 return RETURN_ERR;
5013}
5014
5015// changes the hardware settings to disable encryption on this ap
5016INT wifi_disableApEncryption(INT apIndex)
5017{
5018 //Apply instantly
5019 return RETURN_ERR;
5020}
5021
5022// set the authorization mode on this ap
5023// mode mapping as: 1: open, 2: shared, 4:auto
5024INT wifi_setApAuthMode(INT apIndex, INT mode)
5025{
developeraf95c502022-09-13 16:18:22 +08005026 struct params params={0};
5027 char config_file[64] = {0};
5028 int ret;
5029
5030 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5031
5032 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5033 params.name = "auth_algs";
5034
5035 if (mode & 1 && mode & 2)
5036 params.value = "3";
5037 else if (mode & 2)
5038 params.value = "2";
5039 else if (mode & 1)
5040 params.value = "1";
5041 else
5042 params.value = "0";
5043
5044 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5045 wifi_hostapdWrite(config_file, &params, 1);
5046 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5048
5049 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005050}
5051
5052// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5053INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5054{
5055 //save to wifi config, and wait for wifi restart to apply
5056 struct params params={'\0'};
5057 char config_file[MAX_BUF_SIZE] = {0};
5058 int ret;
5059
5060 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5061 if(authMode == NULL)
5062 return RETURN_ERR;
5063
5064 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5065 params.name = "wpa_key_mgmt";
5066
5067 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5068 params.value = "WPA-PSK";
5069 else if(strcmp(authMode,"EAPAuthentication") == 0)
5070 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005071 else if (strcmp(authMode, "SAEAuthentication") == 0)
5072 params.value = "SAE";
5073 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5074 params.value = "WPA-EAP-SUITE-B-192";
developer06a01d92022-09-07 16:32:39 +08005075 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5076 return RETURN_OK; //This is taken careof in beaconType
5077
5078 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5079 ret=wifi_hostapdWrite(config_file,&params,1);
5080 if(!ret)
5081 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5082 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5083
5084 return ret;
5085}
5086
5087// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5088INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5089{
5090 //save to wifi config, and wait for wifi restart to apply
5091 char BeaconType[50] = {0};
5092 char config_file[MAX_BUF_SIZE] = {0};
5093
5094 *authMode = 0;
5095 wifi_getApBeaconType(apIndex,BeaconType);
5096 printf("%s____%s \n",__FUNCTION__,BeaconType);
5097
5098 if(strcmp(BeaconType,"None") == 0)
5099 strcpy(authMode,"None");
5100 else
5101 {
5102 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5103 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5104 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5105 if(strcmp(authMode,"WPA-PSK") == 0)
5106 strcpy(authMode,"SharedAuthentication");
5107 else if(strcmp(authMode,"WPA-EAP") == 0)
5108 strcpy(authMode,"EAPAuthentication");
5109 }
5110
5111 return RETURN_OK;
5112}
5113
5114// Outputs the number of stations associated per AP
5115INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5116{
5117 char cmd[128]={0};
5118 char buf[128]={0};
5119 BOOL status = false;
5120
5121 if(apIndex > MAX_APS)
5122 return RETURN_ERR;
5123
5124 wifi_getApEnable(apIndex,&status);
5125 if (!status)
5126 return RETURN_OK;
5127
5128 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5129 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5130 _syscmd(cmd, buf, sizeof(buf));
5131 sscanf(buf,"%lu", output_ulong);
5132
5133 return RETURN_OK;
5134}
5135
5136// manually removes any active wi-fi association with the device specified on this ap
5137INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5138{
5139 char buf[126]={'\0'};
5140
5141 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5142 system(buf);
5143
5144 return RETURN_OK;
5145}
5146
5147// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5148INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5149{
5150 if(NULL == output_int)
5151 return RETURN_ERR;
5152 *output_int = apIndex%2;
5153 return RETURN_OK;
5154}
5155
5156// sets the radio index for the specific ap
5157INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5158{
5159 //set to config only and wait for wifi reset to apply settings
5160 return RETURN_ERR;
5161}
5162
5163// Get the ACL MAC list per AP
5164INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5165{
5166 char cmd[MAX_CMD_SIZE]={'\0'};
5167 int ret = 0;
5168
5169 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5170 ret = _syscmd(cmd,macArray,buf_size);
5171 if (ret != 0)
5172 return RETURN_ERR;
5173
5174 return RETURN_OK;
5175}
5176
developere6aafda2022-09-13 14:59:28 +08005177INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5178{
5179 char cmd[MAX_CMD_SIZE]={'\0'};
5180 int ret = 0;
5181
5182 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5183 ret = _syscmd(cmd,macArray,buf_size);
5184 if (ret != 0)
5185 return RETURN_ERR;
5186
5187 return RETURN_OK;
5188}
5189
5190
developer06a01d92022-09-07 16:32:39 +08005191// Get the list of stations associated per AP
5192INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5193{
5194 char cmd[128];
5195
5196 if(apIndex > 3) //Currently supporting apIndex upto 3
5197 return RETURN_ERR;
5198 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5199 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5200 _syscmd(cmd, macArray, buf_size);
5201
5202 return RETURN_OK;
5203}
5204
5205// adds the mac address to the filter list
5206//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5207INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5208{
5209 char cmd[MAX_CMD_SIZE]={'\0'};
5210 char buf[MAX_BUF_SIZE]={'\0'};
5211
5212#if 0
5213 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5214 if(_syscmd(cmd,buf,sizeof(buf)))
5215 return RETURN_ERR;
5216#endif
5217 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5218 if(_syscmd(cmd,buf,sizeof(buf)))
5219 return RETURN_ERR;
5220
5221 return RETURN_OK;
5222}
5223
5224// deletes the mac address from the filter list
5225//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5226INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5227{
5228 char cmd[MAX_CMD_SIZE]={'\0'};
5229 char buf[MAX_BUF_SIZE]={'\0'};
5230
5231#if 0
5232 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5233 if(_syscmd(cmd,buf,sizeof(buf)))
5234 return RETURN_ERR;
5235
5236#endif
5237 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5238 if(_syscmd(cmd,buf,sizeof(buf)))
5239 return RETURN_ERR;
5240
5241 return RETURN_OK;
5242}
5243
5244// outputs the number of devices in the filter list
5245INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5246{
developere6aafda2022-09-13 14:59:28 +08005247 char cmd[MAX_BUF_SIZE]={0};
5248 char buf[MAX_CMD_SIZE]={0};
5249
5250 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5251 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005252 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005253
5254 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5255 _syscmd(cmd, buf, sizeof(buf));
5256
5257 *output_uint = atoi(buf);
5258
5259 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5260 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005261}
5262
5263INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5264{
5265 char cmd[128]={'\0'};
5266 char buf[128]={'\0'};
5267
5268 if(strcmp(action,"DENY")==0)
5269 {
5270 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5271 system(buf);
5272 return RETURN_OK;
5273 }
5274
5275 if(strcmp(action,"ALLOW")==0)
5276 {
5277 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5278 system(buf);
5279 return RETURN_OK;
5280 }
5281
5282 return RETURN_ERR;
5283
5284}
5285
5286// enable kick for devices on acl black list
5287INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5288{
5289 char aclArray[512] = {0}, *acl = NULL;
5290 char assocArray[512] = {0}, *asso = NULL;
5291
developere6aafda2022-09-13 14:59:28 +08005292 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005293 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5294
5295 // if there are no devices connected there is nothing to do
5296 if (strlen(assocArray) < 17)
5297 return RETURN_OK;
5298
5299 if (enable == TRUE)
5300 {
5301 //kick off the MAC which is in ACL array (deny list)
5302 acl = strtok(aclArray, "\r\n");
5303 while (acl != NULL) {
5304 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5305 wifi_kickApAssociatedDevice(apIndex, acl);
5306
5307 acl = strtok(NULL, "\r\n");
5308 }
developere6aafda2022-09-13 14:59:28 +08005309 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005310 }
5311 else
5312 {
developere6aafda2022-09-13 14:59:28 +08005313 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005314 }
5315
5316#if 0
5317 //TODO: need to revisit below implementation
5318 char aclArray[512]={0}, *acl=NULL;
5319 char assocArray[512]={0}, *asso=NULL;
5320 char buf[256]={'\0'};
5321 char action[10]={'\0'};
5322 FILE *fr=NULL;
5323 char interface[10]={'\0'};
5324 char config_file[MAX_BUF_SIZE] = {0};
5325
5326 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5327 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5328 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5329 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5330
5331 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5332 system(buf);
5333 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5334 system(buf);
5335 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5336 system(buf);
5337 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5338 system(buf);
5339 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5340 system(buf);
5341
5342 if ( enable == TRUE )
5343 {
5344 int device_count=0;
5345 strcpy(action,"DENY");
5346 //kick off the MAC which is in ACL array (deny list)
5347 acl = strtok (aclArray,",");
5348 while (acl != NULL) {
5349 if(strlen(acl)>=17)
5350 {
5351 apply_rules(apIndex, acl,action,interface);
5352 device_count++;
5353 //Register mac to be blocked ,in syscfg.db persistent storage
5354 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5355 system(buf);
5356 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5357 system(buf);
5358 system("syscfg commit");
5359
5360 wifi_kickApAssociatedDevice(apIndex, acl);
5361 }
5362 acl = strtok (NULL, ",");
5363 }
5364 }
5365 else
5366 {
5367 int device_count=0;
5368 char cmdmac[20]={'\0'};
5369 strcpy(action,"ALLOW");
5370 //kick off the MAC which is not in ACL array (allow list)
5371 acl = strtok (aclArray,",");
5372 while (acl != NULL) {
5373 if(strlen(acl)>=17)
5374 {
5375 apply_rules(apIndex, acl,action,interface);
5376 device_count++;
5377 //Register mac to be Allowed ,in syscfg.db persistent storage
5378 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5379 system(buf);
5380 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5381 system(buf);
5382 sprintf(cmdmac,"%s",acl);
5383 }
5384 acl = strtok (NULL, ",");
5385 }
5386 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5387 system(buf);
5388
5389 //Disconnect the mac which is not in ACL
5390 asso = strtok (assocArray,",");
5391 while (asso != NULL) {
5392 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5393 wifi_kickApAssociatedDevice(apIndex, asso);
5394 asso = strtok (NULL, ",");
5395 }
5396 }
5397#endif
5398 return RETURN_OK;
5399}
5400
5401INT wifi_setPreferPrivateConnection(BOOL enable)
5402{
5403 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5404 char buf[1024] = {0};
5405
5406 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5407 if(enable == TRUE)
5408 {
5409 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5410 sprintf(buf,"ifconfig %s down" ,interface_name);
5411 system(buf);
5412 memset(buf,0,sizeof(buf));
5413 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5414 sprintf(buf,"ifconfig %s down" ,interface_name);
5415 system(buf);
5416 }
5417 else
5418 {
5419 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5420 if(strcmp(ssid_cur_value,"1") == 0)
5421 wifi_RestartPrivateWifi_5G();
5422 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5423 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5424 if(strcmp(ssid_cur_value,"1") == 0)
5425 wifi_RestartHostapd_2G();
5426 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5427 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5428 if(strcmp(ssid_cur_value,"1") == 0)
5429 wifi_RestartHostapd_5G();
5430 }
5431 return RETURN_OK;
5432}
5433
5434// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5435INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5436{
5437 int items = 1;
5438 struct params list[2];
5439 char buf[MAX_BUF_SIZE] = {0};
5440 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005441 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005442
5443 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005444
developer10adcc12022-09-13 14:39:17 +08005445 if (filterMode == 0) {
5446 sprintf(buf, "%d", 0);
5447 list[0].value = buf;
5448
5449 char cmd[128], rtn[128];
5450 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5451 _syscmd(cmd, rtn, sizeof(rtn));
5452 memset(cmd,0,sizeof(cmd));
5453 // Delete deny_mac_file in hostapd configuration
5454 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5455 _syscmd(cmd, rtn, sizeof(rtn));
5456 }
5457 else if (filterMode == 1) {
5458 sprintf(buf, "%d", filterMode);
5459 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005460 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5461 list[1].name = "accept_mac_file";
5462 list[1].value = acl_file;
5463 items = 2;
developer10adcc12022-09-13 14:39:17 +08005464 } else if (filterMode == 2) {
5465 //TODO: deny_mac_file
5466 sprintf(buf, "%d", 0);
5467 list[0].value = buf;
5468 list[1].name = "deny_mac_file";
5469 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5470 list[1].value = deny_file;
5471 items = 2;
5472 } else {
5473 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005474 }
developer10adcc12022-09-13 14:39:17 +08005475
developer06a01d92022-09-07 16:32:39 +08005476 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5477 wifi_hostapdWrite(config_file, list, items);
5478
5479 return RETURN_OK;
5480
5481#if 0
5482 if(apIndex==0 || apIndex==1)
5483 {
5484 //set the filtermode
5485 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5486 system(buf);
5487 system("syscfg commit");
5488
5489 if(filterMode==0)
5490 {
5491 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5492 system(buf);
5493 return RETURN_OK;
5494 }
5495 }
5496 return RETURN_OK;
5497#endif
5498}
5499
5500// 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.
5501INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5502{
5503 return RETURN_ERR;
5504}
5505
5506// gets the vlan ID for this ap from an internal enviornment variable
5507INT wifi_getApVlanID(INT apIndex, INT *output_int)
5508{
5509 if(apIndex=0)
5510 {
5511 *output_int=100;
5512 return RETURN_OK;
5513 }
5514
5515 return RETURN_ERR;
5516}
5517
5518// sets the vlan ID for this ap to an internal enviornment variable
5519INT wifi_setApVlanID(INT apIndex, INT vlanId)
5520{
5521 //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)
5522 return RETURN_ERR;
5523}
5524
5525// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5526INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5527{
5528 snprintf(bridgeName, 32, "brlan0");
5529 snprintf(IP, 32, "10.0.0.1");
5530 snprintf(subnet, 32, "255.255.255.0");
5531
5532 return RETURN_OK;
5533}
5534
5535//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5536INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5537{
5538 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5539 return RETURN_ERR;
5540}
5541
5542// reset the vlan configuration for this ap
5543INT wifi_resetApVlanCfg(INT apIndex)
5544{
developerf5fef612022-09-20 19:38:26 +08005545 char original_config_file[64] = {0};
5546 char current_config_file[64] = {0};
5547 char buf[64] = {0};
5548 char cmd[64] = {0};
5549 char vlan_file[64] = {0};
5550 char vlan_tagged_interface[16] = {0};
5551 char vlan_bridge[16] = {0};
5552 char vlan_naming[16] = {0};
5553 struct params list[4] = {0};
5554 wifi_band band;
5555
5556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5557
5558 band = wifi_index_to_band(apIndex);
5559 if (band == band_2_4)
5560 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5561 else if (band = band_5)
5562 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5563 else if (band = band_6)
5564 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5565
5566 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5567
5568 if (strlen(vlan_file) == 0)
5569 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005570
developerf5fef612022-09-20 19:38:26 +08005571 // The file should exist or this vap would not work.
5572 if (access(vlan_file, F_OK) != 0) {
5573 sprintf(cmd, "touch %s", vlan_file);
5574 _syscmd(cmd, buf, sizeof(buf));
5575 }
5576 list[0].name = "vlan_file";
5577 list[0].value = vlan_file;
5578
5579 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5580 list[1].name = "vlan_tagged_interface";
5581 list[1].value = vlan_tagged_interface;
5582
5583 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5584 list[2].name = "vlan_bridge";
5585 list[2].value = vlan_bridge;
5586
5587 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5588 list[3].name = "vlan_naming";
5589 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005590
developerf5fef612022-09-20 19:38:26 +08005591 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5592 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005593 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005594 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005595
developerf5fef612022-09-20 19:38:26 +08005596 // restart this ap
5597 wifi_setApEnable(apIndex, FALSE);
5598 wifi_setApEnable(apIndex, TRUE);
5599
5600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5601
5602 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005603}
5604
5605// 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.
5606INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5607{
5608 return RETURN_ERR;
5609}
5610
5611// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5612INT wifi_startHostApd()
5613{
5614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5615 system("systemctl start hostapd.service");
5616 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5617 return RETURN_OK;
5618 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5619}
5620
5621// stops hostapd
5622INT wifi_stopHostApd()
5623{
5624 char cmd[128] = {0};
5625 char buf[128] = {0};
5626
5627 sprintf(cmd,"systemctl stop hostapd");
5628 _syscmd(cmd, buf, sizeof(buf));
5629
5630 return RETURN_OK;
5631}
5632
5633// restart hostapd dummy function
5634INT wifi_restartHostApd()
5635{
5636 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5637 system("systemctl restart hostapd-global");
5638 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5639
5640 return RETURN_OK;
5641}
5642
5643static int align_hostapd_config(int index)
5644{
5645 ULONG lval;
5646 wifi_getRadioChannel(index%2, &lval);
5647 wifi_setRadioChannel(index%2, lval);
5648}
5649
5650// sets the AP enable status variable for the specified ap.
5651INT wifi_setApEnable(INT apIndex, BOOL enable)
5652{
5653 char config_file[MAX_BUF_SIZE] = {0};
5654 char cmd[MAX_CMD_SIZE] = {0};
5655 char buf[MAX_BUF_SIZE] = {0};
5656 BOOL status;
5657
5658 wifi_getApEnable(apIndex,&status);
5659 if (enable == status)
5660 return RETURN_OK;
5661
5662 if (enable == TRUE) {
5663 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5664 align_hostapd_config(apIndex);
5665 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5666 //Hostapd will bring up this interface
5667 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5668 _syscmd(cmd, buf, sizeof(buf));
5669 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5670 _syscmd(cmd, buf, sizeof(buf));
5671 }
5672 else {
5673 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5674 _syscmd(cmd, buf, sizeof(buf));
5675 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5676 _syscmd(cmd, buf, sizeof(buf));
5677 }
5678 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5679 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5680 _syscmd(cmd, buf, sizeof(buf));
5681 //Wait for wifi up/down to apply
5682 return RETURN_OK;
5683}
5684
5685// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5686INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5687{
5688 char cmd[MAX_CMD_SIZE] = {'\0'};
5689 char buf[MAX_BUF_SIZE] = {'\0'};
5690
5691 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5692 return RETURN_ERR;
5693
5694 *output_bool = 0;
5695
5696 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5697 {
developer70490032022-09-13 15:45:20 +08005698 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005699 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5700 }
5701
5702 return RETURN_OK;
5703}
5704
5705// Outputs the AP "Enabled" "Disabled" status from driver
5706INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5707{
5708 char cmd[128] = {0};
5709 char buf[128] = {0};
5710 BOOL output_bool;
5711
5712 if ( NULL == output_string)
5713 return RETURN_ERR;
5714 wifi_getApEnable(apIndex,&output_bool);
5715
5716 if(output_bool == 1)
5717 snprintf(output_string, 32, "Up");
5718 else
5719 snprintf(output_string, 32, "Disable");
5720
5721 return RETURN_OK;
5722}
5723
5724//Indicates whether or not beacons include the SSID name.
5725// outputs a 1 if SSID on the AP is enabled, else outputs 0
5726INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5727{
5728 //get the running status
5729 char config_file[MAX_BUF_SIZE] = {0};
5730 char buf[16] = {0};
5731
5732 if (!output)
5733 return RETURN_ERR;
5734
5735 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5736 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5737 *output = (strncmp("0",buf,1) == 0);
5738
5739 return RETURN_OK;
5740}
5741
5742// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5743INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5744{
5745 //store the config, apply instantly
5746 char config_file[MAX_BUF_SIZE] = {0};
5747 struct params list;
5748
5749 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5750 list.name = "ignore_broadcast_ssid";
5751 list.value = enable?"0":"1";
5752
5753 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5754 wifi_hostapdWrite(config_file, &list, 1);
5755 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5756 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005757 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005758 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5759
5760 return RETURN_OK;
5761}
5762
5763//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5764INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5765{
5766 //get the running status
5767 if(!output_uint)
5768 return RETURN_ERR;
5769 *output_uint=16;
5770 return RETURN_OK;
5771}
5772
5773INT wifi_setApRetryLimit(INT apIndex, UINT number)
5774{
5775 //apply instantly
5776 return RETURN_ERR;
5777}
5778
5779//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5780INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5781{
5782 if(!output)
5783 return RETURN_ERR;
5784 *output=TRUE;
5785 return RETURN_OK;
5786}
5787
5788//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5789INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5790{
5791 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005792 char cmd[128] = {0};
5793 char buf[128] = {0};
5794 int max_radio_num = 0, radioIndex = 0;
developer3ab38042022-09-13 14:17:03 +08005795
developer0b246d12022-09-30 15:24:20 +08005796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005797
developer0b246d12022-09-30 15:24:20 +08005798 wifi_getMaxRadioNumber(&max_radio_num);
5799 radioIndex = apIndex % max_radio_num;
5800 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", radioIndex);
5801 _syscmd(cmd,buf, sizeof(buf));
5802
5803 if (strlen(buf) > 0)
5804 *output = true;
5805
5806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005807
developer06a01d92022-09-07 16:32:39 +08005808 return RETURN_OK;
5809}
5810
5811//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5812INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5813{
5814 //get the running status from driver
5815 if(!output)
5816 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005817
5818 char config_file[MAX_BUF_SIZE] = {0};
5819 char buf[16] = {0};
5820
5821 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5822 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5823 if (strncmp("1",buf,1) == 0)
5824 *output = TRUE;
5825 else
5826 *output = FALSE;
5827
developer06a01d92022-09-07 16:32:39 +08005828 return RETURN_OK;
5829}
5830
5831// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5832INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5833{
5834 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005835 char config_file[MAX_BUF_SIZE] = {0};
5836 struct params list;
5837
5838 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5839 list.name = "wmm_enabled";
5840 list.value = enable?"1":"0";
5841
5842 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5843 wifi_hostapdWrite(config_file, &list, 1);
5844 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5845 wifi_reloadAp(apIndex);
5846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5847
5848 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005849}
5850
5851//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.
5852INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5853{
5854 //get the running status from driver
5855 if(!output)
5856 return RETURN_ERR;
5857 *output=TRUE;
5858 return RETURN_OK;
5859}
5860
5861// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5862INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5863{
5864 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005865 char config_file[MAX_BUF_SIZE] = {0};
5866 struct params list;
5867
5868 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5869 list.name = "uapsd_advertisement_enabled";
5870 list.value = enable?"1":"0";
5871
5872 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5873 wifi_hostapdWrite(config_file, &list, 1);
5874 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5875 wifi_reloadAp(apIndex);
5876 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5877
5878 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005879}
5880
developer6daeb3f2022-09-30 13:36:39 +08005881// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005882INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5883{
developer6daeb3f2022-09-30 13:36:39 +08005884 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5885 char cmd[128] = {0};
5886 char buf[128] = {0};
5887 char ack_filepath[128] = {0};
5888 uint16_t bitmap = 0;
5889 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5890 FILE *f = NULL;
5891
5892 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5893
5894 // Get current setting
5895 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
5896 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
5897 _syscmd(cmd, buf, sizeof(buf));
5898 if (strlen(buf) > 0)
5899 bitmap = strtoul(buf, NULL, 10);
5900
5901 bitmap = strtoul(buf, NULL, 10);
5902
5903 if (ackPolicy == TRUE) { // True, unset this class
5904 bitmap &= ~class_map[class];
5905 } else { // False, set this class
5906 bitmap |= class_map[class];
5907 }
5908
5909 f = fopen(ack_filepath, "w");
5910 if (f == NULL) {
5911 fprintf(stderr, "%s: fopen failed\n", __func__);
5912 return RETURN_ERR;
5913 }
5914 fprintf(f, "%hu", bitmap);
5915 fclose(f);
5916
5917 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
5918 _syscmd(cmd, buf, sizeof(buf));
5919
5920 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5921 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005922}
5923
5924//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.
5925INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5926{
5927 //get the running status from driver
5928 if(!output_uint)
5929 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005930
5931 char output[16]={'\0'};
5932 char config_file[MAX_BUF_SIZE] = {0};
5933
5934 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5935 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5936 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5937 else {
5938 int device_num = atoi(output);
5939 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5940 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5941 return RETURN_ERR;
5942 }
5943 else {
5944 *output_uint = device_num;
5945 }
5946 }
5947
developer06a01d92022-09-07 16:32:39 +08005948 return RETURN_OK;
5949}
5950
5951INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5952{
5953 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005954 char str[MAX_BUF_SIZE]={'\0'};
5955 char cmd[MAX_CMD_SIZE]={'\0'};
5956 struct params params;
5957 char config_file[MAX_BUF_SIZE] = {0};
5958
5959 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5960 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5961 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5962 return RETURN_ERR;
5963 }
5964 sprintf(str, "%d", number);
5965 params.name = "max_num_sta";
5966 params.value = str;
5967
5968 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5969 int ret = wifi_hostapdWrite(config_file, &params, 1);
5970 if (ret) {
5971 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5972 ,__func__, ret);
5973 }
5974
5975 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5976 if (ret) {
5977 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5978 ,__func__, ret);
5979 }
5980 wifi_reloadAp(apIndex);
5981 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5982
5983 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005984}
5985
5986//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.
5987INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5988{
5989 //get the current threshold
5990 if(!output_uint)
5991 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005992 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5993 if (*output_uint == 0)
5994 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08005995 return RETURN_OK;
5996}
5997
5998INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
5999{
6000 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006001 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6002 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006003 return RETURN_ERR;
6004}
6005
6006//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.
6007INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6008{
6009 if(!output_uint)
6010 return RETURN_ERR;
6011 *output_uint = 3;
6012 return RETURN_OK;
6013}
6014
6015//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6016INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6017{
6018 if(!output_uint)
6019 return RETURN_ERR;
6020 *output_uint = 3;
6021 return RETURN_OK;
6022}
6023
6024//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.
6025INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6026{
6027 if(!output_in_seconds)
6028 return RETURN_ERR;
6029 *output_in_seconds = 0;
6030 return RETURN_OK;
6031}
6032
6033//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
6034INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6035{
6036 if(!output || apIndex>=MAX_APS)
6037 return RETURN_ERR;
6038 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006039 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006040 return RETURN_OK;
6041}
6042
6043//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6044INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6045{
developer587c1b62022-09-27 15:58:59 +08006046 char config_file[128] = {0};
6047 char wpa[16] = {0};
6048 char key_mgmt[64] = {0};
6049 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006050 if (!output)
6051 return RETURN_ERR;
6052
6053 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006054 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006055
developer587c1b62022-09-27 15:58:59 +08006056 strcpy(output, "None");//Copying "None" to output string for default case
6057 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6058 if (strstr(key_mgmt, "WPA-PSK")) {
6059 if (strcmp(wpa, "1"))
6060 snprintf(output, 32, "WPA-Personal");
6061 else if (strcmp(wpa, "2"))
6062 snprintf(output, 32, "WPA2-Personal");
6063 else if (strcmp(wpa, "3"))
6064 snprintf(output, 32, "WPA-WPA2-Personal");
6065
6066 } else if (strstr(key_mgmt, "WPA-EAP")) {
6067 if (strcmp(wpa, "1"))
6068 snprintf(output, 32, "WPA-Enterprise");
6069 else if (strcmp(wpa, "2"))
6070 snprintf(output, 32, "WPA2-Enterprise");
6071 else if (strcmp(wpa, "3"))
6072 snprintf(output, 32, "WPA-WPA2-Enterprise");
6073 } else if (strstr(key_mgmt, "SAE")) {
6074 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
6075 int disable = strtol(buf, NULL, 16);
6076 if (disable & 0x1)
6077 snprintf(output, 32, "WPA3-Personal");
6078 else
6079 snprintf(output, 32, "WPA3-Transition");
6080 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6081 snprintf(output, 32, "WPA3-Enterprise");
6082 }
developer06a01d92022-09-07 16:32:39 +08006083
6084 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6085 return RETURN_OK;
6086#if 0
6087 //TODO: need to revisit below implementation
6088 char securityType[32], authMode[32];
6089 int enterpriseMode=0;
6090
6091 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6092 if(!output)
6093 return RETURN_ERR;
6094
6095 wifi_getApBeaconType(apIndex, securityType);
6096 strcpy(output,"None");//By default, copying "None" to output string
6097 if (strncmp(securityType,"None", strlen("None")) == 0)
6098 return RETURN_OK;
6099
6100 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6101 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6102
6103 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6104 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6105 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6106 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6107 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6108 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6109 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6110
6111 return RETURN_OK;
6112#endif
6113}
6114
6115INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6116{
6117 char securityType[32];
6118 char authMode[32];
6119
6120 //store settings and wait for wifi up to apply
6121 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6122 if(!encMode)
6123 return RETURN_ERR;
6124
developer06a01d92022-09-07 16:32:39 +08006125 if (strcmp(encMode, "None")==0)
6126 {
6127 strcpy(securityType,"None");
6128 strcpy(authMode,"None");
6129 }
6130 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6131 {
6132 strcpy(securityType,"WPAand11i");
6133 strcpy(authMode,"PSKAuthentication");
6134 }
6135 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6136 {
6137 strcpy(securityType,"WPAand11i");
6138 strcpy(authMode,"EAPAuthentication");
6139 }
6140 else if (strcmp(encMode, "WPA-Personal")==0)
6141 {
6142 strcpy(securityType,"WPA");
6143 strcpy(authMode,"PSKAuthentication");
6144 }
6145 else if (strcmp(encMode, "WPA-Enterprise")==0)
6146 {
6147 strcpy(securityType,"WPA");
6148 strcpy(authMode,"EAPAuthentication");
6149 }
6150 else if (strcmp(encMode, "WPA2-Personal")==0)
6151 {
6152 strcpy(securityType,"11i");
6153 strcpy(authMode,"PSKAuthentication");
6154 }
6155 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6156 {
6157 strcpy(securityType,"11i");
6158 strcpy(authMode,"EAPAuthentication");
6159 }
developer587c1b62022-09-27 15:58:59 +08006160 else if (strcmp(encMode, "WPA3-Personal") == 0)
6161 {
6162 strcpy(securityType,"11i");
6163 strcpy(authMode,"SAEAuthentication");
6164 }
6165 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6166 {
6167 strcpy(securityType,"11i");
6168 strcpy(authMode,"EAP_192-bit_Authentication");
6169 }
developer06a01d92022-09-07 16:32:39 +08006170 else
6171 {
6172 strcpy(securityType,"None");
6173 strcpy(authMode,"None");
6174 }
6175 wifi_setApBeaconType(apIndex, securityType);
6176 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6177 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6178
6179 return RETURN_OK;
6180}
6181
6182
6183//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6184// output_string must be pre-allocated as 64 character string by caller
6185// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6186INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6187{
6188 char buf[16];
6189 char config_file[MAX_BUF_SIZE] = {0};
6190
6191 if(output_string==NULL)
6192 return RETURN_ERR;
6193
6194 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6195 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6196
6197 if(strcmp(buf,"0")==0)
6198 {
6199 printf("wpa_mode is %s ......... \n",buf);
6200 return RETURN_ERR;
6201 }
6202
6203 wifi_dbg_printf("\nFunc=%s\n",__func__);
6204 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6205 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6206 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6207
6208 return RETURN_OK;
6209}
6210
6211// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6212// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6213INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6214{
6215 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6216 struct params params={'\0'};
6217 int ret;
6218 char config_file[MAX_BUF_SIZE] = {0};
6219
6220 if(NULL == preSharedKey)
6221 return RETURN_ERR;
6222
6223 params.name = "wpa_passphrase";
6224
6225 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6226 {
6227 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6228 return RETURN_ERR;
6229 }
6230 params.value = preSharedKey;
6231 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6232 ret = wifi_hostapdWrite(config_file, &params, 1);
6233 if(!ret)
6234 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6235 return ret;
6236 //TODO: call hostapd_cli for dynamic_config_control
6237}
6238
6239//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6240// outputs the passphrase, maximum 63 characters
6241INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6242{
6243 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6244
6245 wifi_dbg_printf("\nFunc=%s\n",__func__);
6246 if (NULL == output_string)
6247 return RETURN_ERR;
6248
6249 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6250 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6251 if(strcmp(buf,"0")==0)
6252 {
6253 printf("wpa_mode is %s ......... \n",buf);
6254 return RETURN_ERR;
6255 }
6256
6257 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6258 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6259
6260 return RETURN_OK;
6261}
6262
6263// sets the passphrase enviornment variable, max 63 characters
6264INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6265{
6266 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6267 struct params params={'\0'};
6268 char config_file[MAX_BUF_SIZE] = {0};
6269 int ret;
6270
6271 if(NULL == passPhrase)
6272 return RETURN_ERR;
6273
6274 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6275 {
6276 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6277 return RETURN_ERR;
6278 }
6279 params.name = "wpa_passphrase";
6280 params.value = passPhrase;
6281 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6282 ret=wifi_hostapdWrite(config_file,&params,1);
6283 if(!ret)
6284 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6285
6286 return ret;
6287}
6288
6289//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.
6290INT wifi_setApSecurityReset(INT apIndex)
6291{
developer8d583982022-09-20 11:28:22 +08006292 char original_config_file[64] = {0};
6293 char current_config_file[64] = {0};
6294 char buf[64] = {0};
6295 char cmd[64] = {0};
6296 char wpa[4] = {0};
6297 char wpa_psk[64] = {0};
6298 char wpa_passphrase[64] = {0};
6299 char wpa_psk_file[128] = {0};
6300 char wpa_key_mgmt[64] = {0};
6301 char wpa_pairwise[32] = {0};
6302 wifi_band band;
6303 struct params list[6];
6304
6305 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6306
6307 band = wifi_index_to_band(apIndex);
6308 if (band == band_2_4)
6309 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6310 else if (band = band_5)
6311 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6312 else if (band = band_6)
6313 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6314 else
6315 return RETURN_ERR;
6316
6317 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6318 list[0].name = "wpa";
6319 list[0].value = wpa;
6320
6321 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6322 list[1].name = "wpa_psk";
6323 list[1].value = wpa_psk;
6324
6325 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6326 list[2].name = "wpa_passphrase";
6327 list[2].value = wpa_passphrase;
6328
6329 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6330
6331 if (strlen(wpa_psk_file) == 0)
6332 strcpy(wpa_psk_file, PSK_FILE);
6333
6334 if (access(wpa_psk_file, F_OK) != 0) {
6335 sprintf(cmd, "touch %s", wpa_psk_file);
6336 _syscmd(cmd, buf, sizeof(buf));
6337 }
6338 list[3].name = "wpa_psk_file";
6339 list[3].value = wpa_psk_file;
6340
6341 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6342 list[4].name = "wpa_key_mgmt";
6343 list[4].value = wpa_key_mgmt;
6344
6345 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6346 list[5].name = "wpa_pairwise";
6347 list[5].value = wpa_pairwise;
6348
6349 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6350 wifi_hostapdWrite(current_config_file, list, 6);
6351
6352 wifi_setApEnable(apIndex, FALSE);
6353 wifi_setApEnable(apIndex, TRUE);
6354
6355 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6356 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006357}
6358
6359//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).
6360INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6361{
developer8f2ddd52022-09-13 15:39:24 +08006362 char config_file[64] = {0};
6363 char buf[64] = {0};
6364 char cmd[256] = {0};
6365
6366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6367
developer06a01d92022-09-07 16:32:39 +08006368 if(!IP_output || !Port_output || !RadiusSecret_output)
6369 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006370
developer8f2ddd52022-09-13 15:39:24 +08006371 // Read the first matched config
6372 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6373 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6374 _syscmd(cmd, buf, sizeof(buf));
6375 strncpy(IP_output, buf, 64);
6376
6377 memset(buf, 0, sizeof(buf));
6378 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6379 _syscmd(cmd, buf, sizeof(buf));
6380 *Port_output = atoi(buf);
6381
6382 memset(buf, 0, sizeof(buf));
6383 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6384 _syscmd(cmd, buf, sizeof(buf));
6385 strncpy(RadiusSecret_output, buf, 64);
6386
6387 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006388 return RETURN_OK;
6389}
6390
6391INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6392{
developer8f2ddd52022-09-13 15:39:24 +08006393 char config_file[64] = {0};
6394 char port_str[8] = {0};
6395 char cmd[256] = {0};
6396 char buf[128] = {0};
6397
6398 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6399
6400 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6401
6402 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6403 _syscmd(cmd, buf, sizeof(buf));
6404 memset(cmd, 0, sizeof(cmd));
6405
6406 snprintf(port_str, sizeof(port_str), "%d", port);
6407 if (strlen(buf) == 0)
6408 // Append
6409 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6410 "auth_server_addr=%s\\n"
6411 "auth_server_port=%s\\n"
6412 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6413 else {
6414 // Delete the three lines setting after the "# radius 1" comment
6415 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6416 _syscmd(cmd, buf, sizeof(buf));
6417 memset(cmd, 0, sizeof(cmd));
6418 // Use "# radius 1" comment to find the location to insert the radius setting
6419 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6420 "# radius 1\\n"
6421 "auth_server_addr=%s\\n"
6422 "auth_server_port=%s\\n"
6423 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6424 }
6425 if(_syscmd(cmd, buf, sizeof(buf))) {
6426 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6427 return RETURN_ERR;
6428 }
6429
6430 wifi_reloadAp(apIndex);
6431 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6432 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006433}
6434
6435INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6436{
developer8f2ddd52022-09-13 15:39:24 +08006437 char config_file[64] = {0};
6438 char buf[64] = {0};
6439 char cmd[256] = {0};
6440
6441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6442
developer06a01d92022-09-07 16:32:39 +08006443 if(!IP_output || !Port_output || !RadiusSecret_output)
6444 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006445
6446 // Read the second matched config
6447 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6448 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6449 _syscmd(cmd, buf, sizeof(buf));
6450 strncpy(IP_output, buf, 64);
6451
6452 memset(buf, 0, sizeof(buf));
6453 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6454 _syscmd(cmd, buf, sizeof(buf));
6455 *Port_output = atoi(buf);
6456
6457 memset(buf, 0, sizeof(buf));
6458 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6459 _syscmd(cmd, buf, sizeof(buf));
6460 strncpy(RadiusSecret_output, buf, 64);
6461
6462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006463 return RETURN_OK;
6464}
6465
6466INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6467{
developer8f2ddd52022-09-13 15:39:24 +08006468 char config_file[64] = {0};
6469 char port_str[8] = {0};
6470 char cmd[256] = {0};
6471 char buf[128] = {0};
6472
6473 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6474
6475 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6476
6477 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6478 _syscmd(cmd, buf, sizeof(buf));
6479 memset(cmd, 0, sizeof(cmd));
6480
6481 snprintf(port_str, sizeof(port_str), "%d", port);
6482 if (strlen(buf) == 0)
6483 // Append
6484 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6485 "auth_server_addr=%s\\n"
6486 "auth_server_port=%s\\n"
6487 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6488 else {
6489 // Delete the three lines setting after the "# radius 2" comment
6490 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6491 _syscmd(cmd, buf, sizeof(buf));
6492 memset(cmd, 0, sizeof(cmd));
6493 // Use "# radius 2" comment to find the location to insert the radius setting
6494 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6495 "# radius 2\\n"
6496 "auth_server_addr=%s\\n"
6497 "auth_server_port=%s\\n"
6498 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6499 }
6500 if(_syscmd(cmd, buf, sizeof(buf))) {
6501 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6502 return RETURN_ERR;
6503 }
6504
6505 wifi_reloadAp(apIndex);
6506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6507 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006508}
6509
6510//RadiusSettings
6511INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6512{
6513 if(!output)
6514 return RETURN_ERR;
6515
6516 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6517 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6518 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6519 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6520 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6521 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.
6522 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6523 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6524 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6525 //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.
6526
6527 return RETURN_OK;
6528}
6529
6530INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6531{
6532 //store the paramters, and apply instantly
6533 return RETURN_ERR;
6534}
6535
6536//Device.WiFi.AccessPoint.{i}.WPS.Enable
6537//Enables or disables WPS functionality for this access point.
6538// outputs the WPS enable state of this ap in output_bool
6539INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6540{
6541 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6542 if(!output_bool || !(apIndex==0 || apIndex==1))
6543 return RETURN_ERR;
6544 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6545 _syscmd(cmd, buf, sizeof(buf));
6546 if(strstr(buf, "configured"))
6547 *output_bool=TRUE;
6548 else
6549 *output_bool=FALSE;
6550
6551 return RETURN_OK;
6552}
6553
6554//Device.WiFi.AccessPoint.{i}.WPS.Enable
6555// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6556INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6557{
6558 char config_file[MAX_BUF_SIZE] = {0};
6559 struct params params;
6560
6561 if(!(apIndex==0 || apIndex==1))
6562 return RETURN_ERR;
6563 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6564 //store the paramters, and wait for wifi up to apply
6565 params.name = "wps_state";
6566 params.value = enable ? "2":"0";
6567
6568 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6569 wifi_hostapdWrite(config_file, &params, 1);
6570 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6571 wifi_reloadAp(apIndex);
6572
6573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6574 return RETURN_OK;
6575}
6576
6577//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
6578INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6579{
6580 if(!output)
6581 return RETURN_ERR;
6582 snprintf(output, 128, "PushButton,PIN");
6583 return RETURN_OK;
6584}
6585
6586//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6587//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.
6588// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6589INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6590{
6591 if(!output)
6592 return RETURN_ERR;
6593 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6594
6595 return RETURN_OK;
6596}
6597
6598//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6599// 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
6600INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6601{
6602 //apply instantly. No setting need to be stored.
6603 char methods[MAX_BUF_SIZE], *token, *next_token;
6604 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6605 struct params params;
6606
6607 if(!methodString || !(apIndex==0 || apIndex==1))
6608 return RETURN_ERR;
6609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6610 //store the paramters, and wait for wifi up to apply
6611
6612 snprintf(methods, sizeof(methods), "%s", methodString);
6613 for(token=methods; *token; token=next_token)
6614 {
6615 strtok_r(token, ",", &next_token);
6616 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6617 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6618 else if(*token=='E')
6619 {
6620 if(!strcmp(methods, "Ethernet"))
6621 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6622 else if(!strcmp(methods, "ExternalNFCToken"))
6623 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6624 else
6625 printf("%s: Unknown WpsConfigMethod\n", __func__);
6626 }
6627 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6628 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6629 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6630 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6631 else if(*token=='P' )
6632 {
6633 if(!strcmp(token, "PushButton"))
6634 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6635 else if(!strcmp(token, "PIN"))
6636 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6637 else
6638 printf("%s: Unknown WpsConfigMethod\n", __func__);
6639 }
6640 else
6641 printf("%s: Unknown WpsConfigMethod\n", __func__);
6642 }
6643 params.name = "config_methods";
6644 params.value = config_methods;
6645 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6646 wifi_hostapdWrite(config_file, &params, 1);
6647 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6648 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6649
6650 return RETURN_OK;
6651}
6652
6653// outputs the pin value, ulong_pin must be allocated by the caller
6654INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6655{
6656 char buf[MAX_BUF_SIZE] = {0};
6657 char cmd[MAX_CMD_SIZE] = {0};
6658
6659 if(!output_ulong || !(apIndex==0 || apIndex==1))
6660 return RETURN_ERR;
6661 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6662 _syscmd(cmd, buf, sizeof(buf));
6663 if(strlen(buf) > 0)
6664 *output_ulong=strtoul(buf, NULL, 10);
6665
6666 return RETURN_OK;
6667}
6668
6669// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6670INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6671{
6672 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6673 char ap_pin[16] = {0};
6674 char buf[MAX_BUF_SIZE] = {0};
6675 char config_file[MAX_BUF_SIZE] = {0};
6676 ULONG prev_pin = 0;
6677 struct params params;
6678
6679 if(!(apIndex==0 || apIndex==1))
6680 return RETURN_ERR;
6681 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6682 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6683 params.name = "ap_pin";
6684 params.value = ap_pin;
6685 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6686 wifi_hostapdWrite(config_file, &params, 1);
6687 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6689
6690 return RETURN_OK;
6691}
6692
6693// Output string is either Not configured or Configured, max 32 characters
6694INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6695{
6696 char cmd[MAX_CMD_SIZE];
6697 char buf[MAX_BUF_SIZE]={0};
6698
6699 if(!output_string || !(apIndex==0 || apIndex==1))
6700 return RETURN_ERR;
6701 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6702 snprintf(output_string, 32, "Not configured");
6703 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6704 _syscmd(cmd, buf, sizeof(buf));
6705
developer348e3d92022-09-13 14:48:41 +08006706 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006707 snprintf(output_string, 32, "Configured");
6708 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6709
6710 return RETURN_OK;
6711}
6712
6713// sets the WPS pin for this AP
6714INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6715{
6716 char cmd[MAX_CMD_SIZE];
6717 char buf[MAX_BUF_SIZE]={0};
6718 BOOL enable;
6719
6720 if(!(apIndex==0 || apIndex==1))
6721 return RETURN_ERR;
6722 wifi_getApEnable(apIndex, &enable);
6723 if (!enable)
6724 return RETURN_ERR;
6725 wifi_getApWpsEnable(apIndex, &enable);
6726 if (!enable)
6727 return RETURN_ERR;
6728
6729 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6730 _syscmd(cmd, buf, sizeof(buf));
6731 if((strstr(buf, "OK"))!=NULL)
6732 return RETURN_OK;
6733
6734 return RETURN_ERR;
6735}
6736
6737// This function is called when the WPS push button has been pressed for this AP
6738INT wifi_setApWpsButtonPush(INT apIndex)
6739{
6740 char cmd[MAX_CMD_SIZE];
6741 char buf[MAX_BUF_SIZE]={0};
6742 BOOL enable=FALSE;
6743
6744 if(!(apIndex==0 || apIndex==1))
6745 return RETURN_ERR;
6746 wifi_getApEnable(apIndex, &enable);
6747 if (!enable)
6748 return RETURN_ERR;
6749
6750 wifi_getApWpsEnable(apIndex, &enable);
6751 if (!enable)
6752 return RETURN_ERR;
6753
6754 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6755 _syscmd(cmd, buf, sizeof(buf));
6756
6757 if((strstr(buf, "OK"))!=NULL)
6758 return RETURN_OK;
6759 return RETURN_ERR;
6760}
6761
6762// cancels WPS mode for this AP
6763INT wifi_cancelApWPS(INT apIndex)
6764{
6765 char cmd[MAX_CMD_SIZE];
6766 char buf[MAX_BUF_SIZE]={0};
6767
6768 if(!(apIndex==0 || apIndex==1))
6769 return RETURN_ERR;
6770 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6771 _syscmd(cmd,buf, sizeof(buf));
6772
6773 if((strstr(buf, "OK"))!=NULL)
6774 return RETURN_OK;
6775 return RETURN_ERR;
6776}
6777
6778//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6779//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6780INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6781{
6782 FILE *f;
6783 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6784 char cmd[256], buf[2048];
6785 char *param , *value, *line=NULL;
6786 size_t len = 0;
6787 ssize_t nread;
6788 wifi_associated_dev_t *dev=NULL;
6789
6790 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6791 *associated_dev_array = NULL;
6792 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6793 _syscmd(cmd,buf,sizeof(buf));
6794 *output_array_size = atoi(buf);
6795
6796 if (*output_array_size <= 0)
6797 return RETURN_OK;
6798
6799 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6800 *associated_dev_array = dev;
6801 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6802 _syscmd(cmd,buf,sizeof(buf));
6803 f = fopen("/tmp/connected_devices.txt", "r");
6804 if (f==NULL)
6805 {
6806 *output_array_size=0;
6807 return RETURN_ERR;
6808 }
6809 while ((nread = getline(&line, &len, f)) != -1)
6810 {
6811 param = strtok(line,"=");
6812 value = strtok(NULL,"=");
6813
6814 if( strcmp("flags",param) == 0 )
6815 {
6816 value[strlen(value)-1]='\0';
6817 if(strstr (value,"AUTHORIZED") != NULL )
6818 {
6819 dev[auth_temp].cli_AuthenticationState = 1;
6820 dev[auth_temp].cli_Active = 1;
6821 auth_temp++;
6822 read_flag=1;
6823 }
6824 }
6825 if(read_flag==1)
6826 {
6827 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6828 {
6829 value[strlen(value)-1]='\0';
6830 sscanf(value, "%x:%x:%x:%x:%x:%x",
6831 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6832 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6833 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6834 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6835 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6836 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6837 mac_temp++;
6838 read_flag=0;
6839 }
6840 }
6841 }
6842 *output_array_size = auth_temp;
6843 auth_temp=0;
6844 mac_temp=0;
6845 free(line);
6846 fclose(f);
6847 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6848 return RETURN_OK;
6849}
6850
6851#define MACADDRESS_SIZE 6
6852
6853INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6854{
6855 FILE *fp = NULL;
6856 char str[MAX_BUF_SIZE] = {0};
6857 int wificlientindex = 0 ;
6858 int count = 0;
6859 int signalstrength = 0;
6860 int arr[MACADDRESS_SIZE] = {0};
6861 unsigned char mac[MACADDRESS_SIZE] = {0};
6862 UINT wifi_count = 0;
6863 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6864 char pipeCmd[MAX_CMD_SIZE] = {0};
6865
6866 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6867 *output_array_size = 0;
6868 *associated_dev_array = NULL;
6869
6870 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6871 fp = popen(pipeCmd, "r");
6872 if (fp == NULL)
6873 {
6874 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6875 return RETURN_ERR;
6876 }
6877
6878 /* Read the output a line at a time - output it. */
6879 fgets(str, sizeof(str)-1, fp);
6880 wifi_count = (unsigned int) atoi ( str );
6881 *output_array_size = wifi_count;
6882 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6883 pclose(fp);
6884
6885 if(wifi_count == 0)
6886 {
6887 return RETURN_OK;
6888 }
6889 else
6890 {
6891 wifi_associated_dev3_t* temp = NULL;
6892 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6893 if(temp == NULL)
6894 {
6895 printf("Error Statement. Insufficient memory \n");
6896 return RETURN_ERR;
6897 }
6898
6899 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6900 system(pipeCmd);
6901 memset(pipeCmd,0,sizeof(pipeCmd));
6902 if(apIndex == 0)
6903 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6904 else if(apIndex == 1)
6905 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6906 system(pipeCmd);
6907
6908 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6909 if(fp == NULL)
6910 {
6911 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6912 return RETURN_ERR;
6913 }
6914 fclose(fp);
6915
6916 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6917 fp = popen(pipeCmd, "r");
6918 if(fp)
6919 {
6920 for(count =0 ; count < wifi_count; count++)
6921 {
6922 fgets(str, MAX_BUF_SIZE, fp);
6923 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6924 {
6925 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6926 {
6927 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6928
6929 }
6930 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6931 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]);
6932 }
6933 temp[count].cli_AuthenticationState = 1; //TODO
6934 temp[count].cli_Active = 1; //TODO
6935 }
6936 pclose(fp);
6937 }
6938
6939 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6940 fp = popen(pipeCmd, "r");
6941 if(fp)
6942 {
6943 pclose(fp);
6944 }
6945 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6946 if(fp)
6947 {
6948 for(count =0 ; count < wifi_count ;count++)
6949 {
6950 fgets(str, MAX_BUF_SIZE, fp);
6951 signalstrength = atoi(str);
6952 temp[count].cli_SignalStrength = signalstrength;
6953 temp[count].cli_RSSI = signalstrength;
6954 temp[count].cli_SNR = signalstrength + 95;
6955 }
6956 pclose(fp);
6957 }
6958
6959
6960 if((apIndex == 0) || (apIndex == 4))
6961 {
6962 for(count =0 ; count < wifi_count ;count++)
6963 {
6964 strcpy(temp[count].cli_OperatingStandard,"g");
6965 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6966 }
6967
6968 //BytesSent
6969 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6970 fp = popen(pipeCmd, "r");
6971 if(fp)
6972 {
6973 pclose(fp);
6974 }
6975 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6976 if(fp)
6977 {
6978 for (count = 0; count < wifi_count; count++)
6979 {
6980 fgets(str, MAX_BUF_SIZE, fp);
6981 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6982 }
6983 pclose(fp);
6984 }
6985
6986 //BytesReceived
6987 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6988 fp = popen(pipeCmd, "r");
6989 if (fp)
6990 {
6991 pclose(fp);
6992 }
6993 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6994 if (fp)
6995 {
6996 for (count = 0; count < wifi_count; count++)
6997 {
6998 fgets(str, MAX_BUF_SIZE, fp);
6999 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7000 }
7001 pclose(fp);
7002 }
7003
7004 //PacketsSent
7005 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7006 fp = popen(pipeCmd, "r");
7007 if (fp)
7008 {
7009 pclose(fp);
7010 }
7011
7012 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7013 if (fp)
7014 {
7015 for (count = 0; count < wifi_count; count++)
7016 {
7017 fgets(str, MAX_BUF_SIZE, fp);
7018 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7019 }
7020 pclose(fp);
7021 }
7022
7023 //PacketsReceived
7024 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7025 fp = popen(pipeCmd, "r");
7026 if (fp)
7027 {
7028 pclose(fp);
7029 }
7030 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7031 if (fp)
7032 {
7033 for (count = 0; count < wifi_count; count++)
7034 {
7035 fgets(str, MAX_BUF_SIZE, fp);
7036 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7037 }
7038 pclose(fp);
7039 }
7040
7041 //ErrorsSent
7042 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7043 fp = popen(pipeCmd, "r");
7044 if (fp)
7045 {
7046 pclose(fp);
7047 }
7048 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7049 if (fp)
7050 {
7051 for (count = 0; count < wifi_count; count++)
7052 {
7053 fgets(str, MAX_BUF_SIZE, fp);
7054 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7055 }
7056 pclose(fp);
7057 }
7058
7059 //ErrorsSent
7060 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7061 fp = popen(pipeCmd, "r");
7062 if (fp)
7063 {
7064 pclose(fp);
7065 }
7066 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7067 if (fp)
7068 {
7069 for (count = 0; count < wifi_count; count++)
7070 {
7071 fgets(str, MAX_BUF_SIZE, fp);
7072 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7073 }
7074 pclose(fp);
7075 }
7076
7077 //LastDataDownlinkRate
7078 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7079 fp = popen(pipeCmd, "r");
7080 if (fp)
7081 {
7082 pclose(fp);
7083 }
7084 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7085 if (fp)
7086 {
7087 for (count = 0; count < wifi_count; count++)
7088 {
7089 fgets(str, MAX_BUF_SIZE, fp);
7090 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7091 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7092 }
7093 pclose(fp);
7094 }
7095
7096 //LastDataUplinkRate
7097 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7098 fp = popen(pipeCmd, "r");
7099 if (fp)
7100 {
7101 pclose(fp);
7102 }
7103 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7104 if (fp)
7105 {
7106 for (count = 0; count < wifi_count; count++)
7107 {
7108 fgets(str, MAX_BUF_SIZE, fp);
7109 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7110 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7111 }
7112 pclose(fp);
7113 }
7114
7115 }
7116 else if ((apIndex == 1) || (apIndex == 5))
7117 {
7118 for (count = 0; count < wifi_count; count++)
7119 {
7120 strcpy(temp[count].cli_OperatingStandard, "a");
7121 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7122 temp[count].cli_BytesSent = 0;
7123 temp[count].cli_BytesReceived = 0;
7124 temp[count].cli_LastDataUplinkRate = 0;
7125 temp[count].cli_LastDataDownlinkRate = 0;
7126 temp[count].cli_PacketsSent = 0;
7127 temp[count].cli_PacketsReceived = 0;
7128 temp[count].cli_ErrorsSent = 0;
7129 }
7130 }
7131
7132 for (count = 0; count < wifi_count; count++)
7133 {
7134 temp[count].cli_Retransmissions = 0;
7135 temp[count].cli_DataFramesSentAck = 0;
7136 temp[count].cli_DataFramesSentNoAck = 0;
7137 temp[count].cli_MinRSSI = 0;
7138 temp[count].cli_MaxRSSI = 0;
7139 strncpy(temp[count].cli_InterferenceSources, "", 64);
7140 memset(temp[count].cli_IPAddress, 0, 64);
7141 temp[count].cli_RetransCount = 0;
7142 temp[count].cli_FailedRetransCount = 0;
7143 temp[count].cli_RetryCount = 0;
7144 temp[count].cli_MultipleRetryCount = 0;
7145 }
7146 *associated_dev_array = temp;
7147 }
7148 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7149 return RETURN_OK;
7150}
7151
7152int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7153{
7154 FILE *fp = NULL;
7155 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7156 char cmd[MAX_CMD_SIZE];
7157 int count = 0;
7158
7159 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7160 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7161 fp = popen(cmd,"r");
7162 if(fp == NULL)
7163 {
7164 printf("Failed to run command in Function %s\n",__FUNCTION__);
7165 return 0;
7166 }
7167 if(fgets(path, sizeof(path)-1, fp) != NULL)
7168 {
7169 for(count=0;path[count]!='\n';count++)
7170 status[count]=path[count];
7171 status[count]='\0';
7172 }
7173 strcpy(wifi_status,status);
7174 pclose(fp);
7175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7176 return RETURN_OK;
7177}
7178
7179/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7180struct hostapd_sta_param {
7181 char key[50];
7182 char value[100];
7183}
7184
7185static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7186 int i = 0;
7187
7188 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7189 if (strncmp(params[i].key,key,50) == 0){
7190 return &params[i].value;
7191 }
7192 i++;
7193 }
7194 return NULL;
7195
7196} */
7197
7198static unsigned int count_occurences(const char *buf, const char *word)
7199{
7200 unsigned int n = 0;
7201 char *ptr = strstr(buf, word);
7202
7203 while (ptr++) {
7204 n++;
7205 ptr = strstr(ptr, word);
7206 }
7207
7208 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7209 return n;
7210}
7211
7212static const char *get_line_from_str_buf(const char *buf, char *line)
7213{
7214 int i;
7215 int n = strlen(buf);
7216
7217 for (i = 0; i < n; i++) {
7218 line[i] = buf[i];
7219 if (buf[i] == '\n') {
7220 line[i] = '\0';
7221 return &buf[i + 1];
7222 }
7223 }
7224
7225 return NULL;
7226}
7227
7228INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7229{
7230 unsigned int assoc_cnt = 0;
7231 char interface_name[50] = {0};
7232 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7233 char cmd[MAX_CMD_SIZE] = {'\0'};
7234 char line[256] = {'\0'};
7235 int i = 0;
7236 int ret = 0;
7237 const char *ptr = NULL;
7238 char *key = NULL;
7239 char *val = NULL;
7240 wifi_associated_dev3_t *temp = NULL;
7241 int rssi;
7242
7243 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7244
7245 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7246 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7247 return RETURN_ERR;
7248 }
7249
7250 // Example filtered output of 'iw dev' command:
7251 // Station 0a:69:72:10:d2:fa (on wifi0)
7252 // signal avg:-67 [-71, -71] dBm
7253 // Station 28:c2:1f:25:5f:99 (on wifi0)
7254 // signal avg:-67 [-71, -70] dBm
7255 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7256 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7257 return RETURN_ERR;
7258 }
7259
7260 ret = _syscmd(cmd, buf, sizeof(buf));
7261 if (ret == RETURN_ERR) {
7262 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7263 return RETURN_ERR;
7264 }
7265
7266 *output_array_size = count_occurences(buf, "Station");
7267 if (*output_array_size == 0) return RETURN_OK;
7268
7269 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7270 if (temp == NULL) {
7271 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7272 return RETURN_ERR;
7273 }
7274 *associated_dev_array = temp;
7275
7276 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7277 ptr = get_line_from_str_buf(buf, line);
7278 i = -1;
7279 while (ptr) {
7280 if (strstr(line, "Station")) {
7281 i++;
7282 key = strtok(line, " ");
7283 val = strtok(NULL, " ");
7284 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7285 &temp[i].cli_MACAddress[0],
7286 &temp[i].cli_MACAddress[1],
7287 &temp[i].cli_MACAddress[2],
7288 &temp[i].cli_MACAddress[3],
7289 &temp[i].cli_MACAddress[4],
7290 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7291 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7292 free(*associated_dev_array);
7293 return RETURN_ERR;
7294 }
7295 }
7296 else if (i < 0) {
7297 ptr = get_line_from_str_buf(ptr, line);
7298 continue; // We didn't detect 'station' entry yet
7299 }
7300 else if (strstr(line, "signal avg")) {
7301 key = strtok(line, ":");
7302 val = strtok(NULL, " ");
7303 if (sscanf(val, "%d", &rssi) <= 0 ) {
7304 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7305 free(*associated_dev_array);
7306 return RETURN_ERR;
7307 }
7308 temp[i].cli_RSSI = rssi;
7309 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7310 }
7311 // Here other fields can be parsed if added to filter of 'iw dev' command
7312
7313 ptr = get_line_from_str_buf(ptr, line);
7314 };
7315
7316 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7317
7318 return RETURN_OK;
7319}
7320
7321#if 0
7322//To-do
7323INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7324{
7325 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7326
7327 //Using different approach to get required WiFi Parameters from system available commands
7328#if 0
7329 FILE *f;
7330 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7331 char cmd[256], buf[2048];
7332 char *param , *value, *line=NULL;
7333 size_t len = 0;
7334 ssize_t nread;
7335 wifi_associated_dev3_t *dev=NULL;
7336 *associated_dev_array = NULL;
7337 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7338 _syscmd(cmd,buf,sizeof(buf));
7339 *output_array_size = atoi(buf);
7340
7341 if (*output_array_size <= 0)
7342 return RETURN_OK;
7343
7344 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7345 *associated_dev_array = dev;
7346 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7347 _syscmd(cmd,buf,sizeof(buf));
7348 f = fopen("/tmp/connected_devices.txt", "r");
7349 if (f==NULL)
7350 {
7351 *output_array_size=0;
7352 return RETURN_ERR;
7353 }
7354 while ((nread = getline(&line, &len, f)) != -1)
7355 {
7356 param = strtok(line,"=");
7357 value = strtok(NULL,"=");
7358
7359 if( strcmp("flags",param) == 0 )
7360 {
7361 value[strlen(value)-1]='\0';
7362 if(strstr (value,"AUTHORIZED") != NULL )
7363 {
7364 dev[auth_temp].cli_AuthenticationState = 1;
7365 dev[auth_temp].cli_Active = 1;
7366 auth_temp++;
7367 read_flag=1;
7368 }
7369 }
7370 if(read_flag==1)
7371 {
7372 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7373 {
7374 value[strlen(value)-1]='\0';
7375 sscanf(value, "%x:%x:%x:%x:%x:%x",
7376 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7377 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7378 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7379 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7380 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7381 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7382
7383 }
7384 else if( strcmp("rx_packets",param) == 0 )
7385 {
7386 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7387 }
7388
7389 else if( strcmp("tx_packets",param) == 0 )
7390 {
7391 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7392 }
7393
7394 else if( strcmp("rx_bytes",param) == 0 )
7395 {
7396 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7397 }
7398
7399 else if( strcmp("tx_bytes",param) == 0 )
7400 {
7401 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7402 mac_temp++;
7403 read_flag=0;
7404 }
7405 }
7406 }
7407
7408 *output_array_size = auth_temp;
7409 auth_temp=0;
7410 mac_temp=0;
7411 free(line);
7412 fclose(f);
7413#endif
7414 char interface_name[MAX_BUF_SIZE] = {0};
7415 char wifi_status[MAX_BUF_SIZE] = {0};
7416 char hostapdconf[MAX_BUF_SIZE] = {0};
7417
7418 wifi_associated_dev3_t *dev_array = NULL;
7419 ULONG wifi_count = 0;
7420
7421 *associated_dev_array = NULL;
7422 *output_array_size = 0;
7423
7424 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7425 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7426 {
7427 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7428
7429 GetInterfaceName(interface_name, hostapdconf);
7430
7431 if(strlen(interface_name) > 1)
7432 {
7433 wifihal_interfacestatus(wifi_status,interface_name);
7434 if(strcmp(wifi_status,"RUNNING") == 0)
7435 {
7436 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7437
7438 *associated_dev_array = dev_array;
7439 *output_array_size = wifi_count;
7440 }
7441 else
7442 {
7443 *associated_dev_array = NULL;
7444 }
7445 }
7446 }
7447
7448 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7449 return RETURN_OK;
7450}
7451#endif
7452
7453/* getIPAddress function */
7454/**
7455* @description Returning IpAddress of the Matched String
7456*
7457* @param
7458* @str Having MacAddress
7459* @ipaddr Having ipaddr
7460* @return The status of the operation
7461* @retval RETURN_OK if successful
7462* @retval RETURN_ERR if any error is detected
7463*
7464*/
7465
7466INT getIPAddress(char *str,char *ipaddr)
7467{
7468 FILE *fp = NULL;
7469 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7470 int LeaseTime = 0,ret = 0;
7471 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7472 {
7473 return RETURN_ERR;
7474 }
7475
7476 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7477 {
7478 /*
7479 Sample:sss
7480 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7481 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7482 */
7483 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7484 &(LeaseTime),
7485 phyAddr,
7486 ipAddr,
7487 hostName
7488 );
7489 if(ret != 4)
7490 continue;
7491 if(strcmp(str,phyAddr) == 0)
7492 strcpy(ipaddr,ipAddr);
7493 }
7494 return RETURN_OK;
7495}
7496
7497/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7498/**
7499* @description Returning Inactive wireless connected clients informations
7500*
7501* @param
7502* @filename Holding private_wifi 2g/5g content files
7503* @associated_dev_array Having inactiv wireless clients informations
7504* @output_array_size Returning Inactive wireless counts
7505* @return The status of the operation
7506* @retval RETURN_OK if successful
7507* @retval RETURN_ERR if any error is detected
7508*
7509*/
7510
7511INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7512{
7513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7514 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7515 FILE *fp = NULL;
7516 int arr[MACADDRESS_SIZE] = {0};
7517 unsigned char mac[MACADDRESS_SIZE] = {0};
7518 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7519 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7520 fp = popen(buf,"r");
7521 if(fp == NULL)
7522 return RETURN_ERR;
7523 else
7524 {
7525 fgets(path,sizeof(path),fp);
7526 maccount = atoi(path);
7527 }
7528 pclose(fp);
7529 *output_array_size = maccount;
7530 wifi_associated_dev3_t* temp = NULL;
7531 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7532 *associated_dev_array = temp;
7533 if(temp == NULL)
7534 {
7535 printf("Error Statement. Insufficient memory \n");
7536 return RETURN_ERR;
7537 }
7538 memset(buf,0,sizeof(buf));
7539 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7540 fp = popen(buf,"r");
7541 for(count = 0; count < maccount ; count++)
7542 {
7543 fgets(path,sizeof(path),fp);
7544 for(i = 0; path[i]!='\n';i++)
7545 str[i]=path[i];
7546 str[i]='\0';
7547 getIPAddress(str,ipaddr);
7548 memset(buf,0,sizeof(buf));
7549 if(strlen(ipaddr) > 0)
7550 {
7551 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7552 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7553 {
7554 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7555 {
7556 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7557 {
7558 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7559
7560 }
7561 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7562 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]);
7563 }
7564 temp[count].cli_AuthenticationState = 0; //TODO
7565 temp[count].cli_Active = 0; //TODO
7566 temp[count].cli_SignalStrength = 0;
7567 }
7568 else //Active wireless clients info
7569 {
7570 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7571 {
7572 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7573 {
7574 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7575
7576 }
7577 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7578 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]);
7579 }
7580 temp[count].cli_Active = 1;
7581 }
7582 }
7583 memset(ipaddr,0,sizeof(ipaddr));
7584 }
7585 pclose(fp);
7586 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7587 return RETURN_OK;
7588}
7589//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7590//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7591//To get Band Steering Capability
7592INT wifi_getBandSteeringCapability(BOOL *support)
7593{
7594 *support = FALSE;
7595 return RETURN_OK;
7596}
7597
7598
7599//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7600//To get Band Steering enable status
7601INT wifi_getBandSteeringEnable(BOOL *enable)
7602{
7603 *enable = FALSE;
7604 return RETURN_OK;
7605}
7606
7607//To turn on/off Band steering
7608INT wifi_setBandSteeringEnable(BOOL enable)
7609{
7610 return RETURN_OK;
7611}
7612
7613//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7614//To get Band Steering AP group
7615INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7616{
7617 if (NULL == output_ApGroup)
7618 return RETURN_ERR;
7619
7620 strcpy(output_ApGroup, "1,2");
7621 return RETURN_OK;
7622}
7623
7624//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7625//to set and read the band steering BandUtilizationThreshold parameters
7626INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7627{
7628 return RETURN_ERR;
7629}
7630
7631INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7632{
7633 return RETURN_ERR;
7634}
7635
7636//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7637//to set and read the band steering RSSIThreshold parameters
7638INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7639{
7640 return RETURN_ERR;
7641}
7642
7643INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7644{
7645 return RETURN_ERR;
7646}
7647
7648
7649//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7650//to set and read the band steering physical modulation rate threshold parameters
7651INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7652{
7653 //If chip is not support, return -1
7654 return RETURN_ERR;
7655}
7656
7657INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7658{
7659 //If chip is not support, return -1
7660 return RETURN_ERR;
7661}
7662
7663//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7664//to set and read the inactivity time (in seconds) for steering under overload condition
7665INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7666{
7667 return RETURN_ERR;
7668}
7669
7670INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7671{
7672 return RETURN_ERR;
7673}
7674
7675//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7676//to set and read the inactivity time (in seconds) for steering under Idle condition
7677INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7678{
7679 return RETURN_ERR;
7680}
7681
7682INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7683{
7684 return RETURN_ERR;
7685}
7686
7687//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7688//pClientMAC[64]
7689//pSourceSSIDIndex[64]
7690//pDestSSIDIndex[64]
7691//pSteeringReason[256]
7692INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7693{
7694 //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
7695 *pSteeringTime=time(NULL);
7696 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7697 return RETURN_OK;
7698}
7699
7700INT wifi_ifConfigDown(INT apIndex)
7701{
7702 INT status = RETURN_OK;
7703 char cmd[64];
7704
7705 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7706 printf("%s: %s\n", __func__, cmd);
7707 system(cmd);
7708
7709 return status;
7710}
7711
7712INT wifi_ifConfigUp(INT apIndex)
7713{
7714 char cmd[128];
7715 char buf[1024];
7716
7717 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7718 _syscmd(cmd, buf, sizeof(buf));
7719 return 0;
7720}
7721
7722//>> Deprecated. Replace with wifi_applyRadioSettings
7723INT wifi_pushBridgeInfo(INT apIndex)
7724{
7725 char ip[32];
7726 char subnet[32];
7727 char bridge[32];
7728 int vlanId;
7729 char cmd[128];
7730 char buf[1024];
7731
7732 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7733 wifi_getApVlanID(apIndex,&vlanId);
7734
7735 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7736 _syscmd(cmd,buf, sizeof(buf));
7737
7738 return 0;
7739}
7740
7741INT wifi_pushChannel(INT radioIndex, UINT channel)
7742{
7743 char cmd[128];
7744 char buf[1024];
7745 int apIndex;
7746
7747 apIndex=(radioIndex==0)?0:1;
7748 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7749 _syscmd(cmd,buf, sizeof(buf));
7750
7751 return 0;
7752}
7753
7754INT wifi_pushChannelMode(INT radioIndex)
7755{
7756 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7757 return RETURN_ERR;
7758}
7759
7760INT wifi_pushDefaultValues(INT radioIndex)
7761{
7762 //Apply Comcast specified default radio settings instantly
7763 //AMPDU=1
7764 //AMPDUFrames=32
7765 //AMPDULim=50000
7766 //txqueuelen=1000
7767
7768 return RETURN_ERR;
7769}
7770
7771INT wifi_pushTxChainMask(INT radioIndex)
7772{
7773 //Apply default TxChainMask instantly
7774 return RETURN_ERR;
7775}
7776
7777INT wifi_pushRxChainMask(INT radioIndex)
7778{
7779 //Apply default RxChainMask instantly
7780 return RETURN_ERR;
7781}
7782
7783INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7784{
7785 INT status;
7786
7787 status = wifi_setSSIDName(apIndex,ssid);
7788 wifi_setApEnable(apIndex,FALSE);
7789 wifi_setApEnable(apIndex,TRUE);
7790
7791 return status;
7792}
7793
7794INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7795{
7796 //Apply default Ssid Advertisement instantly
7797 return RETURN_ERR;
7798}
7799
7800INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7801{
7802 INT status = RETURN_ERR;
7803 *output = 0;
7804 return RETURN_ERR;
7805}
7806
7807INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7808{
7809 return RETURN_OK;
7810}
7811
7812INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7813{
7814 return RETURN_OK;
7815}
7816
7817//To-do
7818INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7819{
developereb199ae2022-09-13 14:04:27 +08007820 char output[16]={'\0'};
7821 char config_file[MAX_BUF_SIZE] = {0};
7822
7823 if (!output_string)
7824 return RETURN_ERR;
7825
7826 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7827 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7828
7829 if (strlen(output) == 0)
7830 snprintf(output_string, 64, "Disabled");
7831 else if (strncmp(output, "0", 1) == 0)
7832 snprintf(output_string, 64, "Disabled");
7833 else if (strncmp(output, "1", 1) == 0)
7834 snprintf(output_string, 64, "Optional");
7835 else if (strncmp(output, "2", 1) == 0)
7836 snprintf(output_string, 64, "Required");
7837 else {
7838 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7839 return RETURN_ERR;
7840 }
7841
7842 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007843 return RETURN_OK;
7844}
7845INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7846{
developereb199ae2022-09-13 14:04:27 +08007847 char str[MAX_BUF_SIZE]={'\0'};
7848 char cmd[MAX_CMD_SIZE]={'\0'};
7849 struct params params;
7850 char config_file[MAX_BUF_SIZE] = {0};
7851
7852 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7853 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7854 return RETURN_ERR;
7855
7856 params.name = "ieee80211w";
7857 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7858 params.value = "0";
7859 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7860 params.value = "1";
7861 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7862 params.value = "2";
7863 else{
7864 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7865 return RETURN_ERR;
7866 }
7867 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7868 wifi_hostapdWrite(config_file, &params, 1);
7869 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007870 return RETURN_OK;
7871}
7872INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7873{
7874 char output[16]={'\0'};
7875 char config_file[MAX_BUF_SIZE] = {0};
7876
7877 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7878 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7879 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7880
7881 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7882 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7883
7884 return RETURN_OK;
7885}
7886
7887INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7888{
7889 return RETURN_OK;
7890}
7891
7892INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7893{
7894 return RETURN_OK;
7895}
7896
7897INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7898{
7899 return RETURN_OK;
7900}
7901
7902INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7903{
7904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7905 char config_file[MAX_BUF_SIZE] = {0};
7906
7907 if (NULL == output)
7908 return RETURN_ERR;
7909 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7910 wifi_hostapdRead(config_file,"hw_mode",output,64);
7911
7912 if(strcmp(output,"b")==0)
7913 sprintf(output, "%s", "1,2,5.5,11");
7914 else if (strcmp(output,"a")==0)
7915 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7916 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7917 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7918
7919 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7920 return RETURN_OK;
7921}
7922
7923INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7924{
7925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7926 char *temp;
7927 char temp_output[128];
7928 char temp_TransmitRates[128];
7929 char config_file[MAX_BUF_SIZE] = {0};
7930
7931 if (NULL == output)
7932 return RETURN_ERR;
7933
7934 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7935 wifi_hostapdRead(config_file,"supported_rates",output,64);
7936
7937 strcpy(temp_TransmitRates,output);
7938 strcpy(temp_output,"");
7939 temp = strtok(temp_TransmitRates," ");
7940 while(temp!=NULL)
7941 {
7942 temp[strlen(temp)-1]=0;
7943 if((temp[0]=='5') && (temp[1]=='\0'))
7944 {
7945 temp="5.5";
7946 }
7947 strcat(temp_output,temp);
7948 temp = strtok(NULL," ");
7949 if(temp!=NULL)
7950 {
7951 strcat(temp_output,",");
7952 }
7953 }
7954 strcpy(output,temp_output);
7955 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7956
7957 return RETURN_OK;
7958}
7959
7960INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7961{
7962 return RETURN_OK;
7963}
7964
7965
7966INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7967{
7968 int i=0;
7969 char *temp;
7970 char temp1[128];
7971 char temp_output[128];
7972 char temp_TransmitRates[128];
7973 struct params params={'\0'};
7974 char config_file[MAX_BUF_SIZE] = {0};
7975
7976 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7977 if(NULL == output)
7978 return RETURN_ERR;
7979
7980 strcpy(temp_TransmitRates,output);
7981
7982 for(i=0;i<strlen(temp_TransmitRates);i++)
7983 {
7984 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7985 {
7986 continue;
7987 }
7988 else
7989 {
7990 return RETURN_ERR;
7991 }
7992 }
7993 strcpy(temp_output,"");
7994 temp = strtok(temp_TransmitRates," ");
7995 while(temp!=NULL)
7996 {
7997 strcpy(temp1,temp);
7998 if(wlanIndex==1)
7999 {
8000 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8001 {
8002 return RETURN_ERR;
8003 }
8004 }
8005
8006 if(strcmp(temp,"5.5")==0)
8007 {
8008 strcpy(temp1,"55");
8009 }
8010 else
8011 {
8012 strcat(temp1,"0");
8013 }
8014 strcat(temp_output,temp1);
8015 temp = strtok(NULL," ");
8016 if(temp!=NULL)
8017 {
8018 strcat(temp_output," ");
8019 }
8020 }
8021 strcpy(output,temp_output);
8022
8023
8024 params.name = "supported_rates";
8025 params.value = output;
8026
8027 wifi_dbg_printf("\n%s:",__func__);
8028 wifi_dbg_printf("params.value=%s\n",params.value);
8029 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8030 wifi_hostapdWrite(config_file,&params,1);
8031 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8032
8033 return RETURN_OK;
8034}
8035
8036
8037static char *sncopy(char *dst, int dst_sz, const char *src)
8038{
8039 if (src && dst && dst_sz > 0) {
8040 strncpy(dst, src, dst_sz);
8041 dst[dst_sz - 1] = '\0';
8042 }
8043 return dst;
8044}
8045
8046static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8047{
8048 if (0 == strcmp(ht_mode, "HT40") ||
8049 0 == strcmp(ht_mode, "HT80") ||
8050 0 == strcmp(ht_mode, "HT160")) {
8051 switch (channel) {
8052 case 1 ... 7:
8053 case 36:
8054 case 44:
8055 case 52:
8056 case 60:
8057 case 100:
8058 case 108:
8059 case 116:
8060 case 124:
8061 case 132:
8062 case 140:
8063 case 149:
8064 case 157:
8065 return 1;
8066 case 8 ... 13:
8067 case 40:
8068 case 48:
8069 case 56:
8070 case 64:
8071 case 104:
8072 case 112:
8073 case 120:
8074 case 128:
8075 case 136:
8076 case 144:
8077 case 153:
8078 case 161:
8079 return -1;
8080 default:
8081 return -EINVAL;
8082 }
8083 }
8084
8085 return -EINVAL;
8086}
8087
8088static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8089{
8090 if (NULL == hw_mode) return;
8091
8092 if (0 == strcmp(hw_mode, "ac"))
8093 sncopy(bw_mode, bw_mode_len, "ht vht");
8094
8095 if (0 == strcmp(hw_mode, "n"))
8096 sncopy(bw_mode, bw_mode_len, "ht");
8097
8098 return;
8099}
8100
8101static int util_chan_to_freq(int chan)
8102{
8103 if (chan == 14)
8104 return 2484;
8105 else if (chan < 14)
8106 return 2407 + chan * 5;
8107 else if (chan >= 182 && chan <= 196)
8108 return 4000 + chan * 5;
8109 else
8110 return 5000 + chan * 5;
8111 return 0;
8112}
8113
8114const int *util_unii_5g_chan2list(int chan, int width)
8115{
8116 static const int lists[] = {
8117 // <width>, <chan1>, <chan2>..., 0,
8118 20, 36, 0,
8119 20, 40, 0,
8120 20, 44, 0,
8121 20, 48, 0,
8122 20, 52, 0,
8123 20, 56, 0,
8124 20, 60, 0,
8125 20, 64, 0,
8126 20, 100, 0,
8127 20, 104, 0,
8128 20, 108, 0,
8129 20, 112, 0,
8130 20, 116, 0,
8131 20, 120, 0,
8132 20, 124, 0,
8133 20, 128, 0,
8134 20, 132, 0,
8135 20, 136, 0,
8136 20, 140, 0,
8137 20, 144, 0,
8138 20, 149, 0,
8139 20, 153, 0,
8140 20, 157, 0,
8141 20, 161, 0,
8142 20, 165, 0,
8143 40, 36, 40, 0,
8144 40, 44, 48, 0,
8145 40, 52, 56, 0,
8146 40, 60, 64, 0,
8147 40, 100, 104, 0,
8148 40, 108, 112, 0,
8149 40, 116, 120, 0,
8150 40, 124, 128, 0,
8151 40, 132, 136, 0,
8152 40, 140, 144, 0,
8153 40, 149, 153, 0,
8154 40, 157, 161, 0,
8155 80, 36, 40, 44, 48, 0,
8156 80, 52, 56, 60, 64, 0,
8157 80, 100, 104, 108, 112, 0,
8158 80, 116, 120, 124, 128, 0,
8159 80, 132, 136, 140, 144, 0,
8160 80, 149, 153, 157, 161, 0,
8161 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8162 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8163 -1 // final delimiter
8164 };
8165 const int *start;
8166 const int *p;
8167
8168 for (p = lists; *p != -1; p++) {
8169 if (*p == width) {
8170 for (start = ++p; *p != 0; p++) {
8171 if (*p == chan)
8172 return start;
8173 }
8174 }
8175 // move to the end of channel list of given width
8176 while (*p != 0) {
8177 p++;
8178 }
8179 }
8180
8181 return NULL;
8182}
8183
8184static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8185{
8186 if (NULL == ht_mode)
8187 return 0;
8188
8189 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8190 const int *chans = util_unii_5g_chan2list(channel, width);
8191 int sum = 0;
8192 int cnt = 0;
8193
8194 if (NULL == chans)
8195 return 0;
8196
8197 while (*chans) {
8198 sum += *chans;
8199 cnt++;
8200 chans++;
8201 }
8202 return sum / cnt;
8203}
8204
8205static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8206{
8207 BOOL onlyG, onlyN, onlyA;
8208 CHAR tmp[64];
8209 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8210 if (ret == RETURN_OK) {
8211 sncopy(hw_mode, hw_mode_size, tmp);
8212 }
8213 return ret;
8214}
8215
8216INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8217{
8218 // Sample commands:
8219 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8220 // hostapd_cli -i wifi0 chan_switch 30 2437
8221 char cmd[MAX_CMD_SIZE] = {0};
8222 char buf[MAX_BUF_SIZE] = {0};
8223 int freq = 0, ret = 0;
8224 char center_freq1_str[32] = ""; // center_freq1=%d
8225 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8226 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8227 char hw_mode[16] = ""; // n|ac
8228 char bw_mode[16] = ""; // ht|ht vht
8229 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8230 int sec_chan_offset;
8231 int width;
developer4fb0b922022-09-30 14:29:09 +08008232 char config_file[64] = {0};
8233 BOOL stbcEnable = FALSE;
8234 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008235
8236 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8237
8238 freq = util_chan_to_freq(channel);
8239
8240 // Get radio mode HT20|HT40|HT80 etc.
8241 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
8242 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8243 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8244 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8245 if (sec_chan_offset != -EINVAL)
8246 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
8247
8248
8249 // Provide bandwith if specified
8250 if (channel_width_MHz > 20) {
8251 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8252 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8253 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
8254
8255 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8256 }
8257
8258 int center_chan = 0;
8259 if (channel_width_MHz > 20) {
8260 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8261 if (center_chan > 0) {
8262 int center_freq1 = util_chan_to_freq(center_chan);
8263 if (center_freq1)
8264 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8265 }
8266 }
8267
8268 {
8269 // Only the first AP, other are hanging on the same radio
8270 int apIndex = radioIndex;
8271 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8272 AP_PREFIX, apIndex, csa_beacon_count, freq,
8273 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8274 wifi_dbg_printf("execute: '%s'\n", cmd);
8275 ret = _syscmd(cmd, buf, sizeof(buf));
8276 }
8277
8278 wifi_setRadioChannel(radioIndex, channel);
8279
developer4fb0b922022-09-30 14:29:09 +08008280 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8281 _syscmd(cmd, buf, sizeof(buf));
8282 if (strlen(buf) != 0)
8283 stbcEnable = TRUE;
8284
developer06a01d92022-09-07 16:32:39 +08008285 char *ext_str = "None";
8286 if (sec_chan_offset == 1) ext_str = "Above";
8287 else if (sec_chan_offset == -1) ext_str = "Below";
8288 wifi_setRadioExtChannel(radioIndex, ext_str);
8289
8290 wifi_setRadioCenterChannel(radioIndex, center_chan);
8291
developer4fb0b922022-09-30 14:29:09 +08008292 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8293
developer06a01d92022-09-07 16:32:39 +08008294 char mhz_str[16];
8295 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8296 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8297
8298 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8299
8300 return RETURN_OK;
8301}
8302
8303INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8304{
developer615510b2022-09-27 10:14:35 +08008305 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008306 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008307 char cmd[256]={0};
8308 char buf[128]={0};
8309 char file_name[32] = {0};
8310 char filter_SSID[32] = {0};
8311 char line[256] = {0};
8312 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008313 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008314 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008315 size_t len=0;
8316 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008317 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008318 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008319 bool filter_enable = false;
8320 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008321
developer615510b2022-09-27 10:14:35 +08008322 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008323
developer615510b2022-09-27 10:14:35 +08008324 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8325 f = fopen(file_name, "r");
8326 if (f != NULL) {
8327 fgets(filter_SSID, sizeof(file_name), f);
8328 if (strlen(filter_SSID) != 0)
8329 filter_enable = true;
8330 fclose(f);
8331 }
8332
8333 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8334 _syscmd(cmd, buf, sizeof(buf));
8335 channels_num = strtol(buf, NULL, 10);
8336
developer615510b2022-09-27 10:14:35 +08008337 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8338 // 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);
8339 fprintf(stderr, "cmd: %s\n", cmd);
8340 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008341 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8342 return RETURN_ERR;
8343 }
developer5550e242022-09-30 09:59:32 +08008344
8345 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8346 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8347
developer615510b2022-09-27 10:14:35 +08008348 ret = fgets(line, sizeof(line), f);
8349 while (ret != NULL) {
8350 if(strstr(line, "BSS") != NULL) { // new neighbor info
8351 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8352 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8353 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8354
8355 if (!filter_BSS) {
8356 index++;
8357 wifi_neighbor_ap2_t *tmp;
8358 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8359 if (tmp == NULL) { // no more memory to use
8360 index--;
8361 wifi_dbg_printf("%s: realloc failed\n", __func__);
8362 break;
8363 }
8364 scan_array = tmp;
8365 }
8366 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008367
developer615510b2022-09-27 10:14:35 +08008368 filter_BSS = false;
8369 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8370 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8371 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8372 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8373 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008374 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008375 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008376
developer615510b2022-09-27 10:14:35 +08008377 if (freq >= 2412 && freq <= 2484) {
8378 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8379 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8380 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8381 }
8382 else if (freq >= 5160 && freq <= 5805) {
8383 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8384 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8385 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8386 }
developer06a01d92022-09-07 16:32:39 +08008387
developer615510b2022-09-27 10:14:35 +08008388 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008389 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008390 for (int i = 0; i < channels_num; i++) {
8391 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8392 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8393 break;
8394 }
8395 }
developer06a01d92022-09-07 16:32:39 +08008396 }
developer615510b2022-09-27 10:14:35 +08008397 } else if (strstr(line, "beacon interval") != NULL) {
8398 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8399 } else if (strstr(line, "signal") != NULL) {
8400 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8401 } else if (strstr(line,"SSID") != NULL) {
8402 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8403 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8404 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008405 }
developer615510b2022-09-27 10:14:35 +08008406 } else if (strstr(line, "Supported rates") != NULL) {
8407 char SRate[80] = {0}, *tmp = NULL;
8408 memset(buf, 0, sizeof(buf));
8409 strcpy(SRate, line);
8410 tmp = strtok(SRate, ":");
8411 tmp = strtok(NULL, ":");
8412 strcpy(buf, tmp);
8413 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008414
developer615510b2022-09-27 10:14:35 +08008415 tmp = strtok(buf, " \n");
8416 while (tmp != NULL) {
8417 strcat(SRate, tmp);
8418 if (SRate[strlen(SRate) - 1] == '*') {
8419 SRate[strlen(SRate) - 1] = '\0';
8420 }
8421 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008422
developer615510b2022-09-27 10:14:35 +08008423 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008424 }
developer615510b2022-09-27 10:14:35 +08008425 SRate[strlen(SRate) - 1] = '\0';
8426 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8427 } else if (strstr(line, "DTIM") != NULL) {
8428 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8429 } else if (strstr(line, "VHT capabilities") != NULL) {
8430 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8431 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8432 } else if (strstr(line, "HT capabilities") != NULL) {
8433 strcat(scan_array[index].ap_SupportedStandards, ",n");
8434 strcpy(scan_array[index].ap_OperatingStandards, "n");
8435 } else if (strstr(line, "VHT operation") != NULL) {
8436 ret = fgets(line, sizeof(line), f);
8437 sscanf(line," * channel width: %d", &vht_channel_width);
8438 if(vht_channel_width == 1) {
8439 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8440 } else {
8441 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8442 }
8443 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8444 continue;
8445 } else if (strstr(line, "HT operation") != NULL) {
8446 ret = fgets(line, sizeof(line), f);
8447 sscanf(line," * secondary channel offset: %s", &buf);
8448 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008449 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008450 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 +08008451 }
developer615510b2022-09-27 10:14:35 +08008452 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008453 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008454 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8455 } else {
8456 //20Mhz
8457 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 +08008458 }
developer615510b2022-09-27 10:14:35 +08008459 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008460 continue;
developer615510b2022-09-27 10:14:35 +08008461 } else if (strstr(line, "HE capabilities") != NULL) {
8462 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8463 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8464 ret = fgets(line, sizeof(line), f);
8465 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8466 if (strstr(line, "HE40/2.4GHz") != NULL)
8467 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8468 else
8469 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8470 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8471 if (strstr(line, "HE80/5GHz") != NULL) {
8472 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8473 ret = fgets(line, sizeof(line), f);
8474 } else
8475 continue;
8476 if (strstr(line, "HE160/5GHz") != NULL)
8477 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008478 }
developer615510b2022-09-27 10:14:35 +08008479 continue;
8480 } else if (strstr(line, "WPA") != NULL) {
8481 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8482 } else if (strstr(line, "RSN") != NULL) {
8483 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8484 } else if (strstr(line, "Group cipher") != NULL) {
8485 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8486 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8487 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008488 }
developer06a01d92022-09-07 16:32:39 +08008489 }
developer615510b2022-09-27 10:14:35 +08008490 ret = fgets(line, sizeof(line), f);
8491 }
8492
8493 if (!filter_BSS) {
8494 *output_array_size = index + 1;
8495 } else {
8496 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8497 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008498 }
developer06a01d92022-09-07 16:32:39 +08008499 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008500 pclose(f);
developer5550e242022-09-30 09:59:32 +08008501 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008502 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008503 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008504}
developer615510b2022-09-27 10:14:35 +08008505
developer06a01d92022-09-07 16:32:39 +08008506INT wifi_getApAssociatedDeviceStats(
8507 INT apIndex,
8508 mac_address_t *clientMacAddress,
8509 wifi_associated_dev_stats_t *associated_dev_stats,
8510 u64 *handle)
8511{
8512 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8513 char interface_name[50] = {0};
8514 char cmd[1024] = {0};
8515 char mac_str[18] = {0};
8516 char *key = NULL;
8517 char *val = NULL;
8518 FILE *f = NULL;
8519 char *line = NULL;
8520 size_t len = 0;
8521 ssize_t read = 0;
8522
8523 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8524 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8525 return RETURN_ERR;
8526 }
8527
8528 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8529 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8530 if((f = popen(cmd, "r")) == NULL) {
8531 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8532 return RETURN_ERR;
8533 }
8534
8535 while ((read = getline(&line, &len, f)) != -1) {
8536 key = strtok(line,":");
8537 val = strtok(NULL,":");
8538
8539 if(!strncmp(key,"rx bytes",8))
8540 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8541 if(!strncmp(key,"tx bytes",8))
8542 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8543 if(!strncmp(key,"rx packets",10))
8544 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8545 if(!strncmp(key,"tx packets",10))
8546 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8547 if(!strncmp(key,"tx retries",10))
8548 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8549 if(!strncmp(key,"tx failed",9))
8550 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8551 if(!strncmp(key,"rx drop misc",13))
8552 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8553 if(!strncmp(key,"rx bitrate",10)) {
8554 val = strtok(val, " ");
8555 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8556 }
8557 if(!strncmp(key,"tx bitrate",10)) {
8558 val = strtok(val, " ");
8559 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8560 }
8561 }
8562 free(line);
8563 pclose(f);
8564 return RETURN_OK;
8565}
8566
8567INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8568{
8569 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8570
8571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8572 if (NULL == output_string)
8573 return RETURN_ERR;
8574
8575 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8576 _syscmd(cmd, buf, sizeof(buf));
8577
8578 //size of SSID name restricted to value less than 32 bytes
8579 snprintf(output_string, 32, "%s", buf);
8580 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8581
8582 return RETURN_OK;
8583}
8584
8585INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8586{
8587 //char cmd[MAX_CMD_SIZE] = {0};
8588 char config_file[MAX_BUF_SIZE] = {0};
8589 char buf[32] = {0};
8590
8591 if (!output_filterMode)
8592 return RETURN_ERR;
8593
8594 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8595 //_syscmd(cmd, buf, sizeof(buf));
8596 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8597 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008598 if(strlen(buf) == 0) {
8599 *output_filterMode = 0;
8600 }
8601 else {
8602 int macaddr_acl_mode = strtol(buf, NULL, 10);
8603 if (macaddr_acl_mode == 1) {
8604 *output_filterMode = 1;
8605 } else if (macaddr_acl_mode == 0) {
8606 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8607 if (strlen(buf) == 0) {
8608 *output_filterMode = 0;
8609 } else {
8610 *output_filterMode = 2;
8611 }
8612 } else {
8613 return RETURN_ERR;
8614 }
8615 }
developer06a01d92022-09-07 16:32:39 +08008616
8617 return RETURN_OK;
8618}
8619
8620INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8621{
8622 FILE *fp = NULL;
8623 char str[MAX_BUF_SIZE] = {0};
8624 int wificlientindex = 0 ;
8625 int count = 0;
8626 int signalstrength = 0;
8627 int arr[MACADDRESS_SIZE] = {0};
8628 unsigned char mac[MACADDRESS_SIZE] = {0};
8629 UINT wifi_count = 0;
8630 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8631 char pipeCmd[MAX_CMD_SIZE] = {0};
8632
8633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8634 *output_array_size = 0;
8635 *associated_dev_array = NULL;
8636 char interface_name[50] = {0};
8637
8638 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8639 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8640 return RETURN_ERR;
8641 }
8642
8643 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8644 fp = popen(pipeCmd, "r");
8645 if (fp == NULL)
8646 {
8647 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8648 return RETURN_ERR;
8649 }
8650
8651 /* Read the output a line at a time - output it. */
8652 fgets(str, sizeof(str)-1, fp);
8653 wifi_count = (unsigned int) atoi ( str );
8654 *output_array_size = wifi_count;
8655 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8656 pclose(fp);
8657
8658 if(wifi_count == 0)
8659 {
8660 return RETURN_OK;
8661 }
8662 else
8663 {
8664 wifi_associated_dev2_t* temp = NULL;
8665 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8666 *associated_dev_array = temp;
8667 if(temp == NULL)
8668 {
8669 printf("Error Statement. Insufficient memory \n");
8670 return RETURN_ERR;
8671 }
8672
8673 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8674 system(pipeCmd);
8675
8676 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8677 if(fp == NULL)
8678 {
8679 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8680 return RETURN_ERR;
8681 }
8682 fclose(fp);
8683
8684 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8685 fp = popen(pipeCmd, "r");
8686 if(fp)
8687 {
8688 for(count =0 ; count < wifi_count; count++)
8689 {
8690 fgets(str, MAX_BUF_SIZE, fp);
8691 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8692 {
8693 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8694 {
8695 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8696
8697 }
8698 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8699 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]);
8700 }
8701 temp[count].cli_AuthenticationState = 1; //TODO
8702 temp[count].cli_Active = 1; //TODO
8703 }
8704 pclose(fp);
8705 }
8706
8707 //Updating RSSI per client
8708 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8709 fp = popen(pipeCmd, "r");
8710 if(fp)
8711 {
8712 pclose(fp);
8713 }
8714 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8715 if(fp)
8716 {
8717 for(count =0 ; count < wifi_count ;count++)
8718 {
8719 fgets(str, MAX_BUF_SIZE, fp);
8720 signalstrength = atoi(str);
8721 temp[count].cli_RSSI = signalstrength;
8722 }
8723 pclose(fp);
8724 }
8725
8726
8727 //LastDataDownlinkRate
8728 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8729 fp = popen(pipeCmd, "r");
8730 if (fp)
8731 {
8732 pclose(fp);
8733 }
8734 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8735 if (fp)
8736 {
8737 for (count = 0; count < wifi_count; count++)
8738 {
8739 fgets(str, MAX_BUF_SIZE, fp);
8740 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8741 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8742 }
8743 pclose(fp);
8744 }
8745
8746 //LastDataUplinkRate
8747 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8748 fp = popen(pipeCmd, "r");
8749 if (fp)
8750 {
8751 pclose(fp);
8752 }
8753 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8754 if (fp)
8755 {
8756 for (count = 0; count < wifi_count; count++)
8757 {
8758 fgets(str, MAX_BUF_SIZE, fp);
8759 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8760 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8761 }
8762 pclose(fp);
8763 }
8764 }
8765 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8766 return RETURN_OK;
8767
8768}
8769
8770INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8771{
8772#if 0
8773 /*char buf[1024] = {0};
8774 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8775 _syscmd(cmd, buf, sizeof(buf));*/
8776
8777 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8778 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8779 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8780 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8781
8782 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.
8783 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].
8784 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].
8785 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].
8786 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8787 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8788
8789 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8790 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8791 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8792 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.
8793 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.
8794 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.
8795 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.
8796 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.
8797 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.
8798 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.
8799 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8800#endif
8801
8802 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008803 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008804 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008805 char pipeCmd[128] = {0};
8806 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008807 wifi_ssidTrafficStats2_t *out = output_struct;
8808
developerce736392022-09-13 15:24:34 +08008809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008810 if (!output_struct)
8811 return RETURN_ERR;
8812
developerce736392022-09-13 15:24:34 +08008813 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8814 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8815 GetInterfaceName(interface_name, HConf_file);
8816 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008817
developer06a01d92022-09-07 16:32:39 +08008818 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008819 if (fp == NULL) {
8820 fprintf(stderr, "%s: popen failed\n", __func__);
8821 return RETURN_ERR;
8822 }
8823 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008824
developerce736392022-09-13 15:24:34 +08008825 if (strlen(str) == 0) // interface not exist
8826 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008827
developerce736392022-09-13 15:24:34 +08008828 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8829 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008830 pclose(fp);
8831
developerce736392022-09-13 15:24:34 +08008832 memset(str, 0, sizeof(str));
8833 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008834 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008835 if (fp == NULL) {
8836 fprintf(stderr, "%s: popen failed\n", __func__);
8837 return RETURN_ERR;
8838 }
8839 fgets(str, sizeof(str), fp);
8840
8841 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8842 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008843 pclose(fp);
developerce736392022-09-13 15:24:34 +08008844
8845 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8846 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8847
8848 // Not supported
8849 output_struct->ssid_RetransCount = 0;
8850 output_struct->ssid_FailedRetransCount = 0;
8851 output_struct->ssid_RetryCount = 0;
8852 output_struct->ssid_MultipleRetryCount = 0;
8853 output_struct->ssid_ACKFailureCount = 0;
8854 output_struct->ssid_AggregatedPacketCount = 0;
8855
developer06a01d92022-09-07 16:32:39 +08008856 return RETURN_OK;
8857}
8858
8859//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).
8860INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8861{
8862 char output_val[16]={'\0'};
8863 char config_file[MAX_BUF_SIZE] = {0};
8864
8865 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8866 if (!output)
8867 return RETURN_ERR;
8868 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8869 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8870
8871 if( strcmp(output_val,"1") == 0 )
8872 *output = TRUE;
8873 else
8874 *output = FALSE;
8875 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8876
8877 return RETURN_OK;
8878}
8879
8880INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8881{
8882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8883 char str[MAX_BUF_SIZE]={'\0'};
8884 char string[MAX_BUF_SIZE]={'\0'};
8885 char cmd[MAX_CMD_SIZE]={'\0'};
8886 char *ch;
8887 char config_file[MAX_BUF_SIZE] = {0};
8888 struct params params;
8889
8890 if(enable == TRUE)
8891 strcpy(string,"1");
8892 else
8893 strcpy(string,"0");
8894
8895 params.name = "ap_isolate";
8896 params.value = string;
8897
8898 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8899 wifi_hostapdWrite(config_file,&params,1);
8900 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8901
8902 return RETURN_OK;
8903}
8904
8905INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8906{
8907 if (NULL == output_dBm)
8908 return RETURN_ERR;
8909
8910 *output_dBm = 0;
8911 return RETURN_OK;
8912}
8913
8914INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8915{
8916 return RETURN_OK;
8917}
8918INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8919{
8920 return RETURN_OK;
8921}
8922INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8923{
8924 return RETURN_OK;
8925}
8926INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8927{
8928 return RETURN_OK;
8929}
8930INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8931{
8932 return RETURN_OK;
8933}
8934INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8935{
8936 char config_file[MAX_BUF_SIZE] = {0};
8937 struct params list;
8938
8939 list.name = "bss_transition";
8940 list.value = activate?"1":"0";
8941 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8942 wifi_hostapdWrite(config_file, &list, 1);
8943
8944 return RETURN_OK;
8945}
8946wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8947
8948void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8949{
8950 return;
8951}
8952
8953INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8954{
8955 // TODO Implement me!
8956 return RETURN_OK;
8957}
8958
8959INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8960{
developera3c68b92022-09-13 15:27:29 +08008961 char file_name[128] = {0};
8962 char buf[128] = {0};
8963 FILE *f = NULL;
8964
8965 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8966
8967 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8968 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8969 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8970 f = fopen(file_name, "w");
8971 if (f == NULL)
8972 return RETURN_ERR;
8973 // For mode == 0 is to disable filter, just don't write to the file.
8974 if (mode)
8975 fprintf(f, "%s", essid);
8976
8977 fclose(f);
8978 }
8979 } else { // special case, need to set AP's SSID as filter for each radio.
8980 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8981 f = fopen(file_name, "w");
8982 if (f == NULL)
8983 return RETURN_ERR;
8984
8985 // For mode == 0 is to disable filter, just don't write to the file.
8986 if (mode)
8987 fprintf(f, "%s", essid);
8988
8989 fclose(f);
8990 }
8991
8992 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008993 return RETURN_OK;
8994}
8995
8996INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
8997{
8998 // TODO Implement me!
8999 //Apply wifi_pushRadioChannel() instantly
9000 return RETURN_ERR;
9001}
9002
9003INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9004{
9005 // TODO Implement me!
9006 return RETURN_OK;
9007}
9008
9009#ifdef HAL_NETLINK_IMPL
9010static int tidStats_callback(struct nl_msg *msg, void *arg) {
9011 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9012 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9013 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9014 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9015 int rem , tid_index = 0;
9016
9017 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9018 wifi_associated_dev_tid_entry_t *stats_entry;
9019
9020 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9021 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9022 };
9023 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9024 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9025 };
9026
9027 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9028 genlmsg_attrlen(gnlh, 0), NULL);
9029
9030
9031 if (!tb[NL80211_ATTR_STA_INFO]) {
9032 fprintf(stderr, "station stats missing!\n");
9033 return NL_SKIP;
9034 }
9035
9036 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9037 tb[NL80211_ATTR_STA_INFO],
9038 stats_policy)) {
9039 fprintf(stderr, "failed to parse nested attributes!\n");
9040 return NL_SKIP;
9041 }
9042
9043 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9044 {
9045 stats_entry = &out->tid_array[tid_index];
9046
9047 stats_entry->tid = tid_index;
9048 stats_entry->ac = _tid_ac_index_get[tid_index];
9049
9050 if(sinfo[NL80211_STA_INFO_TID_STATS])
9051 {
9052 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9053 printf("failed to parse nested stats attributes!");
9054 return NL_SKIP;
9055 }
9056 }
9057 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9058 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9059
9060 if(tid_index < (PS_MAX_TID - 1))
9061 tid_index++;
9062 }
9063 //ToDo: sum_time_ms, ewma_time_ms
9064 return NL_SKIP;
9065}
9066#endif
9067
9068INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9069{
9070#ifdef HAL_NETLINK_IMPL
9071 Netlink nl;
9072 char if_name[10];
9073
9074 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9075
9076 nl.id = initSock80211(&nl);
9077
9078 if (nl.id < 0) {
9079 fprintf(stderr, "Error initializing netlink \n");
9080 return -1;
9081 }
9082
9083 struct nl_msg* msg = nlmsg_alloc();
9084
9085 if (!msg) {
9086 fprintf(stderr, "Failed to allocate netlink message.\n");
9087 nlfree(&nl);
9088 return -2;
9089 }
9090
9091 genlmsg_put(msg,
9092 NL_AUTO_PORT,
9093 NL_AUTO_SEQ,
9094 nl.id,
9095 0,
9096 0,
9097 NL80211_CMD_GET_STATION,
9098 0);
9099
9100 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9101 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9102 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9103 nl_send_auto(nl.socket, msg);
9104 nl_recvmsgs(nl.socket, nl.cb);
9105 nlmsg_free(msg);
9106 nlfree(&nl);
9107 return RETURN_OK;
9108#else
9109//iw implementation
9110#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9111#define TOTAL_MAX_LINES 50
9112
9113 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9114 char if_name[10];
9115 FILE *fp=NULL;
9116 char pipeCmd[1024]= {'\0'};
9117 int lines,tid_index=0;
9118 char mac_addr[20] = {'\0'};
9119
9120 wifi_associated_dev_tid_entry_t *stats_entry;
9121
9122 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9123 strcpy(mac_addr,clientMacAddress);
9124
9125 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9126 fp= popen(pipeCmd,"r");
9127 if(fp == NULL)
9128 {
9129 perror("popen for station dump failed\n");
9130 return RETURN_ERR;
9131 }
9132 pclose(fp);
9133
9134 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9135 fp=popen(pipeCmd,"r");
9136 if(fp == NULL)
9137 {
9138 perror("popen for grep station failed\n");
9139 return RETURN_ERR;
9140 }
9141 else if(fgets(buf,sizeof(buf),fp) != NULL)
9142 lines=atoi(buf);
9143 else
9144 {
9145 pclose(fp);
9146 fprintf(stderr,"No devices are connected \n");
9147 return RETURN_ERR;
9148 }
9149 pclose(fp);
9150
9151 if(lines == 1)
9152 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9153
9154 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9155 {
9156 stats_entry = &tid_stats->tid_array[tid_index];
9157 stats_entry->tid = tid_index;
9158
9159 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);
9160
9161 fp=popen(pipeCmd,"r");
9162 if(fp ==NULL)
9163 {
9164 perror("Failed to read from tid file \n");
9165 return RETURN_ERR;
9166 }
9167 else if(fgets(buf,sizeof(buf),fp) != NULL)
9168 stats_entry->num_msdus = atol(buf);
9169
9170 pclose(fp);
9171 stats_entry->ac = _tid_ac_index_get[tid_index];
9172// TODO:
9173// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9174// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9175 }
9176 return RETURN_OK;
9177#endif
9178}
9179
9180
9181INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9182{
developer615510b2022-09-27 10:14:35 +08009183 char cmd[128]={0};
9184 char buf[128]={0};
9185 int freq = 0;
9186
9187 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9188
9189 // full mode is used to scan all channels.
9190 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9191 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9192 ieee80211_channel_to_frequency(chan_list[0], &freq);
9193
9194 if (freq)
9195 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9196 else
9197 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9198
9199 _syscmd(cmd, buf, sizeof(buf));
9200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9201
developer06a01d92022-09-07 16:32:39 +08009202 return RETURN_OK;
9203}
9204
9205
9206INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9207{
9208 // TODO Implement me!
9209 return RETURN_ERR;
9210}
9211
9212INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9213{
9214 // TODO Implement me!
9215 return RETURN_ERR;
9216}
9217
9218INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9219{
9220 // TODO Implement me!
9221 return RETURN_ERR;
9222}
9223
9224INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9225{
9226 // TODO Implement me!
9227 return RETURN_ERR;
9228}
9229
9230INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9231{
9232 // TODO Implement me!
9233 return RETURN_ERR;
9234}
9235
9236INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9237{
9238 // TODO Implement me!
9239 return RETURN_ERR;
9240}
9241
9242INT wifi_steering_eventUnregister(void)
9243{
9244 // TODO Implement me!
9245 return RETURN_ERR;
9246}
9247
9248INT wifi_delApAclDevices(INT apIndex)
9249{
9250#if 0
9251 char cmd[MAX_BUF_SIZE] = {0};
9252 char buf[MAX_BUF_SIZE] = {0};
9253
9254 /* Not reset proof solution */
9255 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9256 if(_syscmd(cmd,buf,sizeof(buf)))
9257 return RETURN_ERR;
9258#endif
developere6aafda2022-09-13 14:59:28 +08009259 char cmd[MAX_CMD_SIZE]={0};
9260 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009261
developere6aafda2022-09-13 14:59:28 +08009262 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9263 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9264 if(_syscmd(cmd, buf, sizeof(buf)))
9265 return RETURN_ERR;
9266 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009267
9268 return RETURN_OK;
9269}
9270
9271#ifdef HAL_NETLINK_IMPL
9272static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9273 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9274 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9275 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9276 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9277 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9278 char mac_addr[20],dev[20];
9279
9280 nla_parse(tb,
9281 NL80211_ATTR_MAX,
9282 genlmsg_attrdata(gnlh, 0),
9283 genlmsg_attrlen(gnlh, 0),
9284 NULL);
9285
9286 if(!tb[NL80211_ATTR_STA_INFO]) {
9287 fprintf(stderr, "sta stats missing!\n");
9288 return NL_SKIP;
9289 }
9290
9291 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9292 fprintf(stderr, "failed to parse nested attributes!\n");
9293 return NL_SKIP;
9294 }
9295 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9296
9297 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9298
9299 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9300 fprintf(stderr, "failed to parse nested rate attributes!");
9301 return NL_SKIP;
9302 }
9303
9304 if(sinfo[NL80211_STA_INFO_TID_STATS])
9305 {
9306 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9307 printf("failed to parse nested stats attributes!");
9308 return NL_SKIP;
9309 }
9310 }
9311
9312 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9313 {
9314 printf("Type is VHT\n");
9315 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9316 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9317
9318 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9319 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9320 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9321 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9322 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9323 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9324 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9325 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9326 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9327 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9328 }
9329 else
9330 {
9331 printf(" OFDM or CCK \n");
9332 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9333 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9334 }
9335
9336 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9337 if(rinfo[NL80211_RATE_INFO_MCS])
9338 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9339 }
9340 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9341 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9342 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9343 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9344
9345 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9346 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9347
9348 if (sinfo[NL80211_STA_INFO_SIGNAL])
9349 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9350 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9351 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9352 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9353 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9354 //rssi_array need to be filled
9355 return NL_SKIP;
9356}
9357#endif
9358
9359INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9360{
9361#ifdef HAL_NETLINK_IMPL
9362 Netlink nl;
9363 char if_name[10];
9364
9365 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9366
9367 if (*output_array_size <= 0)
9368 return RETURN_OK;
9369
9370 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9371 nl.id = initSock80211(&nl);
9372
9373 if (nl.id < 0) {
9374 fprintf(stderr, "Error initializing netlink \n");
9375 return 0;
9376 }
9377
9378 struct nl_msg* msg = nlmsg_alloc();
9379
9380 if (!msg) {
9381 fprintf(stderr, "Failed to allocate netlink message.\n");
9382 nlfree(&nl);
9383 return 0;
9384 }
9385
9386 genlmsg_put(msg,
9387 NL_AUTO_PORT,
9388 NL_AUTO_SEQ,
9389 nl.id,
9390 0,
9391 0,
9392 NL80211_CMD_GET_STATION,
9393 0);
9394
9395 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9396 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9397 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9398 nl_send_auto(nl.socket, msg);
9399 nl_recvmsgs(nl.socket, nl.cb);
9400 nlmsg_free(msg);
9401 nlfree(&nl);
9402 return RETURN_OK;
9403#else
9404 //TODO Implement me
9405 return RETURN_OK;
9406#endif
9407}
9408
9409#ifdef HAL_NETLINK_IMPL
9410static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9411 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9412 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9413 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9414 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9415 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9416 char mac_addr[20],dev[20];
9417
9418 nla_parse(tb,
9419 NL80211_ATTR_MAX,
9420 genlmsg_attrdata(gnlh, 0),
9421 genlmsg_attrlen(gnlh, 0),
9422 NULL);
9423
9424 if(!tb[NL80211_ATTR_STA_INFO]) {
9425 fprintf(stderr, "sta stats missing!\n");
9426 return NL_SKIP;
9427 }
9428
9429 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9430 fprintf(stderr, "failed to parse nested attributes!\n");
9431 return NL_SKIP;
9432 }
9433
9434 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9435
9436 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9437
9438 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9439 fprintf(stderr, "failed to parse nested rate attributes!");
9440 return NL_SKIP;
9441 }
9442
9443 if(sinfo[NL80211_STA_INFO_TID_STATS])
9444 {
9445 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9446 printf("failed to parse nested stats attributes!");
9447 return NL_SKIP;
9448 }
9449 }
9450 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9451 {
9452 printf("Type is VHT\n");
9453 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9454 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9455
9456 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9457 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9458 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9459 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9460 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9461 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9462 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9463 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9464 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9465 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9466 }
9467 else
9468 {
9469 printf(" OFDM or CCK \n");
9470 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9471 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9472 }
9473
9474 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9475 if(rinfo[NL80211_RATE_INFO_MCS])
9476 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9477 }
9478
9479 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9480 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9481 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9482 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9483
9484 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9485 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9486 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9487
9488 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9489 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9490
9491 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9492 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9493
9494 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9495 ((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]);
9496
9497 return NL_SKIP;
9498}
9499#endif
9500
9501INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9502{
9503#ifdef HAL_NETLINK_IMPL
9504 Netlink nl;
9505 char if_name[10];
9506
9507 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9508
9509 if (*output_array_size <= 0)
9510 return RETURN_OK;
9511
9512 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9513
9514 nl.id = initSock80211(&nl);
9515
9516 if(nl.id < 0) {
9517 fprintf(stderr, "Error initializing netlink \n");
9518 return 0;
9519 }
9520
9521 struct nl_msg* msg = nlmsg_alloc();
9522
9523 if(!msg) {
9524 fprintf(stderr, "Failed to allocate netlink message.\n");
9525 nlfree(&nl);
9526 return 0;
9527 }
9528
9529 genlmsg_put(msg,
9530 NL_AUTO_PORT,
9531 NL_AUTO_SEQ,
9532 nl.id,
9533 0,
9534 0,
9535 NL80211_CMD_GET_STATION,
9536 0);
9537
9538 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9539 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9540 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9541 nl_send_auto(nl.socket, msg);
9542 nl_recvmsgs(nl.socket, nl.cb);
9543 nlmsg_free(msg);
9544 nlfree(&nl);
9545 return RETURN_OK;
9546#else
9547 //TODO Implement me
9548 return RETURN_OK;
9549#endif
9550}
9551
9552INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9553{
9554 // TODO Implement me!
9555 char buf[MAX_BUF_SIZE] = {0};
9556 char config_file[MAX_BUF_SIZE] = {0};
9557
9558 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9559 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9560 *activate = (strncmp("1",buf,1) == 0);
9561
9562 return RETURN_OK;
9563}
9564
9565INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9566{
9567 char config_file[MAX_BUF_SIZE] = {0};
9568 struct params list;
9569
9570 list.name = "rrm_neighbor_report";
9571 list.value = activate?"1":"0";
9572 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9573 wifi_hostapdWrite(config_file, &list, 1);
9574
9575 return RETURN_OK;
9576}
9577
9578INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9579{
9580 char buf[32] = {0};
9581 char config_file[MAX_BUF_SIZE] = {0};
9582
9583 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9584 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9585 *activate = (strncmp("1",buf,1) == 0);
9586
9587 return RETURN_OK;
9588}
9589#undef HAL_NETLINK_IMPL
9590#ifdef HAL_NETLINK_IMPL
9591static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9592 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9593 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9594 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9595 char dev[20];
9596 int freq =0 ;
9597 static int i=0;
9598
9599 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9600
9601 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9602 };
9603
9604 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9605
9606 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9607
9608 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9609 fprintf(stderr, "survey data missing!\n");
9610 return NL_SKIP;
9611 }
9612
9613 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9614 {
9615 fprintf(stderr, "failed to parse nested attributes!\n");
9616 return NL_SKIP;
9617 }
9618
9619
9620 if(out[0].array_size == 1 )
9621 {
9622 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9623 {
9624 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9625 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9626 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9627
9628 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9629 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9630 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9631 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9632 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9633 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9634 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9635 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9636 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9637 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9638 if (sinfo[NL80211_SURVEY_INFO_TIME])
9639 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9640 return NL_STOP;
9641 }
9642 }
9643 else
9644 {
9645 if ( i <= out[0].array_size )
9646 {
9647 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9648 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9649 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9650
9651 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9652 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9653 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9654 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9655 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9656 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9657 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9658 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9659 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9660 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9661 if (sinfo[NL80211_SURVEY_INFO_TIME])
9662 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9663 }
9664 }
9665
9666 i++;
9667 return NL_SKIP;
9668}
9669#endif
9670
9671static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9672{
9673 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9674 FILE *fp;
9675
9676 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9677 {
9678 printf("Creating Frequency-Channel Map\n");
9679 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9680 }
9681 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9682 if((fp = popen(command, "r")))
9683 {
9684 fgets(output, sizeof(output), fp);
9685 *freqMHz = atoi(output);
9686 fclose(fp);
9687 }
9688
9689 return 0;
9690}
9691
9692static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9693{
9694 int freqMHz = -1;
9695 char cmd[MAX_CMD_SIZE] = {'\0'};
9696
9697 ieee80211_channel_to_frequency(channel, &freqMHz);
9698 if (freqMHz == -1) {
9699 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9700 return -1;
9701 }
9702
9703 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9704 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9705 radioIndex, freqMHz);
9706 return -1;
9707 }
9708
9709 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9710 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9711 return -1;
9712 }
9713
9714 return 0;
9715}
9716
9717static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9718{
9719 const char *ptr = buf;
9720 char *key = NULL;
9721 char *val = NULL;
9722 char line[256] = { '\0' };
9723
9724 while (ptr = get_line_from_str_buf(ptr, line)) {
9725 if (strstr(line, "Frequency")) continue;
9726
9727 key = strtok(line, ":");
9728 val = strtok(NULL, " ");
9729 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9730
9731 if (!strcmp(key, "noise")) {
9732 sscanf(val, "%d", &stats->ch_noise);
9733 if (stats->ch_noise == 0) {
9734 // Workaround for missing noise information.
9735 // Assume -95 for 2.4G and -103 for 5G
9736 if (radioIndex == 0) stats->ch_noise = -95;
9737 if (radioIndex == 1) stats->ch_noise = -103;
9738 }
9739 }
9740 else if (!strcmp(key, "channel active time")) {
9741 sscanf(val, "%llu", &stats->ch_utilization_total);
9742 }
9743 else if (!strcmp(key, "channel busy time")) {
9744 sscanf(val, "%llu", &stats->ch_utilization_busy);
9745 }
9746 else if (!strcmp(key, "channel receive time")) {
9747 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9748 }
9749 else if (!strcmp(key, "channel transmit time")) {
9750 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9751 }
9752 };
9753
9754 return 0;
9755}
9756
9757INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9758{
9759 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9760#ifdef HAL_NETLINK_IMPL
9761 Netlink nl;
9762 wifi_channelStats_t_loc local[array_size];
9763 char if_name[10];
9764
9765 local[0].array_size = array_size;
9766
9767 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9768
9769 nl.id = initSock80211(&nl);
9770
9771 if (nl.id < 0) {
9772 fprintf(stderr, "Error initializing netlink \n");
9773 return -1;
9774 }
9775
9776 struct nl_msg* msg = nlmsg_alloc();
9777
9778 if (!msg) {
9779 fprintf(stderr, "Failed to allocate netlink message.\n");
9780 nlfree(&nl);
9781 return -2;
9782 }
9783
9784 genlmsg_put(msg,
9785 NL_AUTO_PORT,
9786 NL_AUTO_SEQ,
9787 nl.id,
9788 0,
9789 NLM_F_DUMP,
9790 NL80211_CMD_GET_SURVEY,
9791 0);
9792
9793 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9794 nl_send_auto(nl.socket, msg);
9795 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9796 nl_recvmsgs(nl.socket, nl.cb);
9797 nlmsg_free(msg);
9798 nlfree(&nl);
9799 //Copying the Values
9800 for(int i=0;i<array_size;i++)
9801 {
9802 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9803 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9804 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9805 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9806 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9807 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9808 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9809 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9810 }
9811#else
9812 ULONG channel = 0;
9813 int i;
9814 int number_of_channels = array_size;
9815 char buf[512];
9816 INT ret;
9817 wifi_channelStats_t tmp_stats;
9818
9819 if (number_of_channels == 0) {
9820 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9821 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9822 return RETURN_ERR;
9823 }
9824 number_of_channels = 1;
9825 input_output_channelStats_array[0].ch_number = channel;
9826 }
9827
9828 for (i = 0; i < number_of_channels; i++) {
9829
9830 input_output_channelStats_array[i].ch_noise = 0;
9831 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9832 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9833 input_output_channelStats_array[i].ch_utilization_busy = 0;
9834 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9835 input_output_channelStats_array[i].ch_utilization_total = 0;
9836
9837 memset(buf, 0, sizeof(buf));
9838 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9839 return RETURN_ERR;
9840 }
9841 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9842 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9843 return RETURN_ERR;
9844 }
9845
9846 // XXX: fake missing 'self' counter which is not available in iw survey output
9847 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9848 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9849
9850 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9851 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9852 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9853 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9854 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9855
9856 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",
9857 __func__,
9858 input_output_channelStats_array[i].ch_number,
9859 input_output_channelStats_array[i].ch_noise,
9860 input_output_channelStats_array[i].ch_utilization_total,
9861 input_output_channelStats_array[i].ch_utilization_busy,
9862 input_output_channelStats_array[i].ch_utilization_busy_rx,
9863 input_output_channelStats_array[i].ch_utilization_busy_tx,
9864 input_output_channelStats_array[i].ch_utilization_busy_self,
9865 input_output_channelStats_array[i].ch_utilization_busy_ext);
9866 }
9867#endif
9868 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9869 return RETURN_OK;
9870}
9871#define HAL_NETLINK_IMPL
9872
9873/* Hostapd events */
9874
9875#ifndef container_of
9876#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9877#define container_of(ptr, type, member) \
9878 ((type *)((char *)ptr - offset_of(type, member)))
9879#endif /* container_of */
9880
9881struct ctrl {
9882 char sockpath[128];
9883 char sockdir[128];
9884 char bss[IFNAMSIZ];
9885 char reply[4096];
9886 int ssid_index;
9887 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9888 void (*overrun)(struct ctrl *ctrl);
9889 struct wpa_ctrl *wpa;
9890 unsigned int ovfl;
9891 size_t reply_len;
9892 int initialized;
9893 ev_timer retry;
9894 ev_timer watchdog;
9895 ev_stat stat;
9896 ev_io io;
9897};
9898static wifi_newApAssociatedDevice_callback clients_connect_cb;
9899static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9900static struct ctrl wpa_ctrl[MAX_APS];
9901static int initialized;
9902
9903static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9904{
9905 char cbuf[256] = {};
9906 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9907 struct cmsghdr *cmsg;
9908 unsigned int ovfl = ctrl->ovfl;
9909 unsigned int drop;
9910
9911 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9912 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9913 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9914 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9915
9916 drop = ovfl - ctrl->ovfl;
9917 ctrl->ovfl = ovfl;
9918
9919 return drop;
9920}
9921
9922static void ctrl_close(struct ctrl *ctrl)
9923{
9924 if (ctrl->io.cb)
9925 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9926 if (ctrl->retry.cb)
9927 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9928 if (!ctrl->wpa)
9929 return;
9930
9931 wpa_ctrl_detach(ctrl->wpa);
9932 wpa_ctrl_close(ctrl->wpa);
9933 ctrl->wpa = NULL;
9934 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9935}
9936
9937static void ctrl_process(struct ctrl *ctrl)
9938{
9939 const char *str;
9940 int drops;
9941 int level;
9942 int err;
9943
9944 /* Example events:
9945 *
9946 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9947 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9948 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9949 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9950 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9951 */
9952 if (!(str = index(ctrl->reply, '>')))
9953 return;
9954 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9955 return;
9956
9957 str++;
9958
9959 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9960 if (!(str = index(ctrl->reply, ' ')))
9961 return;
9962 wifi_associated_dev_t sta;
9963 memset(&sta, 0, sizeof(sta));
9964
9965 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9966 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9967 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9968
9969 sta.cli_Active=true;
9970
9971 (clients_connect_cb)(ctrl->ssid_index, &sta);
9972 goto handled;
9973 }
9974
9975 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9976 if (!(str = index(ctrl->reply, ' ')))
9977 return;
9978
9979 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9980 goto handled;
9981 }
9982
9983 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9984 printf("CTRL_WPA: handle TERMINATING event\n");
9985 goto retry;
9986 }
9987
9988 if (strncmp("AP-DISABLED", str, 11) == 0) {
9989 printf("CTRL_WPA: handle AP-DISABLED\n");
9990 goto retry;
9991 }
9992
9993 printf("Event not supported!!\n");
9994
9995handled:
9996
9997 if ((drops = ctrl_get_drops(ctrl))) {
9998 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
9999 if (ctrl->overrun)
10000 ctrl->overrun(ctrl);
10001 }
10002
10003 return;
10004
10005retry:
10006 printf("WPA_CTRL: closing\n");
10007 ctrl_close(ctrl);
10008 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10009 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10010}
10011
10012static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10013{
10014 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10015 int err;
10016
10017 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10018 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10019 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10020 ctrl->reply[ctrl->reply_len] = 0;
10021 if (err < 0) {
10022 if (errno == EAGAIN || errno == EWOULDBLOCK)
10023 return;
10024 ctrl_close(ctrl);
10025 ev_timer_again(EV_A_ &ctrl->retry);
10026 return;
10027 }
10028
10029 ctrl_process(ctrl);
10030}
10031
10032static int ctrl_open(struct ctrl *ctrl)
10033{
10034 int fd;
10035
10036 if (ctrl->wpa)
10037 return 0;
10038
10039 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10040 if (!ctrl->wpa)
10041 goto err;
10042
10043 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10044 goto err_close;
10045
10046 fd = wpa_ctrl_get_fd(ctrl->wpa);
10047 if (fd < 0)
10048 goto err_detach;
10049
10050 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10051 goto err_detach;
10052
10053 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10054 ev_io_start(EV_DEFAULT_ &ctrl->io);
10055
10056 return 0;
10057
10058err_detach:
10059 wpa_ctrl_detach(ctrl->wpa);
10060err_close:
10061 wpa_ctrl_close(ctrl->wpa);
10062err:
10063 ctrl->wpa = NULL;
10064 return -1;
10065}
10066
10067static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10068{
10069 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10070
10071 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10072 ctrl_open(ctrl);
10073}
10074
10075static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10076{
10077 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10078
10079 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10080 if (ctrl_open(ctrl) == 0) {
10081 printf("WPA_CTRL: retry successful\n");
10082 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10083 }
10084}
10085
10086int ctrl_enable(struct ctrl *ctrl)
10087{
10088 if (ctrl->wpa)
10089 return 0;
10090
10091 if (!ctrl->stat.cb) {
10092 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10093 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10094 }
10095
10096 if (!ctrl->retry.cb) {
10097 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10098 }
10099
10100 return ctrl_open(ctrl);
10101}
10102
10103static void
10104ctrl_msg_cb(char *buf, size_t len)
10105{
10106 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10107
10108 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10109 ctrl_process(ctrl);
10110}
10111
10112static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10113{
10114 int err;
10115
10116 if (!ctrl->wpa)
10117 return -1;
10118 if (*reply_len < 2)
10119 return -1;
10120
10121 (*reply_len)--;
10122 ctrl->reply_len = sizeof(ctrl->reply);
10123 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10124 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10125 if (err < 0)
10126 return err;
10127
10128 if (ctrl->reply_len > *reply_len)
10129 ctrl->reply_len = *reply_len;
10130
10131 *reply_len = ctrl->reply_len;
10132 memcpy(reply, ctrl->reply, *reply_len);
10133 reply[*reply_len - 1] = 0;
10134 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10135 return 0;
10136}
10137
10138static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10139{
10140 const char *pong = "PONG";
10141 const char *ping = "PING";
10142 char reply[1024];
10143 size_t len = sizeof(reply);
10144 int err;
10145 ULONG s, snum;
10146 INT ret;
10147 BOOL status;
10148
10149 printf("WPA_CTRL: watchdog cb\n");
10150
10151 ret = wifi_getSSIDNumberOfEntries(&snum);
10152 if (ret != RETURN_OK) {
10153 printf("%s: failed to get SSID count", __func__);
10154 return;
10155 }
10156
10157 if (snum > MAX_APS) {
10158 printf("more ssid than supported! %lu\n", snum);
10159 return;
10160 }
10161
10162 for (s = 0; s < snum; s++) {
10163 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10164 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10165 continue;
10166 }
10167 if (status == false) continue;
10168
10169 memset(reply, 0, sizeof(reply));
10170 len = sizeof(reply);
10171 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10172 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10173 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10174 continue;
10175
10176 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10177 ctrl_close(&wpa_ctrl[s]);
10178 printf("WPA_CTRL: ev_timer_again %d\n", s);
10179 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10180 }
10181}
10182
10183static int init_wpa()
10184{
10185 int ret = 0, i = 0;
10186 ULONG s, snum;
10187
10188 ret = wifi_getSSIDNumberOfEntries(&snum);
10189 if (ret != RETURN_OK) {
10190 printf("%s: failed to get SSID count", __func__);
10191 return RETURN_ERR;
10192 }
10193
10194 if (snum > MAX_APS) {
10195 printf("more ssid than supported! %lu\n", snum);
10196 return RETURN_ERR;
10197 }
10198
10199 for (s = 0; s < snum; s++) {
10200 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10201 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10202 wpa_ctrl[s].ssid_index = s;
10203 ctrl_enable(&wpa_ctrl[s]);
10204 }
10205
10206 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10207 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10208
10209 initialized = 1;
10210 printf("WPA_CTRL: initialized\n");
10211
10212 return RETURN_OK;
10213}
10214
10215void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10216{
10217 clients_connect_cb = callback_proc;
10218 if (!initialized)
10219 init_wpa();
10220}
10221
10222void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10223{
10224 clients_disconnect_cb = callback_proc;
10225 if (!initialized)
10226 init_wpa();
10227}
10228
10229INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10230{
10231 // TODO Implement me!
10232 return RETURN_ERR;
10233}
10234
10235INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10236{
10237 // TODO Implement me!
10238 return RETURN_ERR;
10239}
10240
10241INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10242{
10243 int i;
10244 char cmd[256];
10245 char channel_numbers_buf[256];
10246 char dfs_state_buf[256];
10247 char line[256];
10248 const char *ptr;
10249
10250 memset(cmd, 0, sizeof(cmd));
10251 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10252 memset(line, 0, sizeof(line));
10253 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10254 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10255
10256 if (radioIndex == 0) { // 2.4G - all allowed
10257 if (outputMapSize < 11) {
10258 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10259 return RETURN_ERR;
10260 }
10261
10262 for (i = 0; i < 11; i++) {
10263 outputMap[i].ch_number = i + 1;
10264 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10265 }
10266
10267 return RETURN_OK;
10268 }
10269
10270 if (radioIndex == 1) { // 5G
10271// Example output of iw list:
10272//
10273// Frequencies:
10274// * 5180 MHz [36] (17.0 dBm)
10275// * 5200 MHz [40] (17.0 dBm)
10276// * 5220 MHz [44] (17.0 dBm)
10277// * 5240 MHz [48] (17.0 dBm)
10278// * 5260 MHz [52] (23.0 dBm) (radar detection)
10279// DFS state: usable (for 78930 sec)
10280// DFS CAC time: 60000 ms
10281// * 5280 MHz [56] (23.0 dBm) (radar detection)
10282// DFS state: usable (for 78930 sec)
10283// DFS CAC time: 60000 ms
10284// * 5300 MHz [60] (23.0 dBm) (radar detection)
10285// DFS state: usable (for 78930 sec)
10286// DFS CAC time: 60000 ms
10287// * 5320 MHz [64] (23.0 dBm) (radar detection)
10288// DFS state: usable (for 78930 sec)
10289// DFS CAC time: 60000 ms
10290// * 5500 MHz [100] (disabled)
10291// * 5520 MHz [104] (disabled)
10292// * 5540 MHz [108] (disabled)
10293// * 5560 MHz [112] (disabled)
10294//
10295// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10296 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10297 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10298 return RETURN_ERR;
10299 }
10300
10301 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10302 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10303 return RETURN_ERR;
10304 }
10305
10306 ptr = channel_numbers_buf;
10307 i = 0;
10308 while (ptr = get_line_from_str_buf(ptr, line)) {
10309 if (i >= outputMapSize) {
10310 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10311 return RETURN_ERR;
10312 }
10313 sscanf(line, "%d", &outputMap[i].ch_number);
10314
10315 memset(cmd, 0, sizeof(cmd));
10316 // Below command should fetch string for DFS state (usable, available or unavailable)
10317 // Example line: "DFS state: usable (for 78930 sec)"
10318 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) {
10319 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10320 return RETURN_ERR;
10321 }
10322
10323 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10324 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10325 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10326 return RETURN_ERR;
10327 }
10328
10329 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10330
10331 if (!strcmp(dfs_state_buf, "usable")) {
10332 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10333 } else if (!strcmp(dfs_state_buf, "available")) {
10334 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10335 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10336 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10337 } else {
10338 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10339 }
10340 i++;
10341 }
10342
10343 return RETURN_OK;
10344 }
10345
10346 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10347 return RETURN_ERR;
10348}
10349
10350INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10351{
10352 // TODO Implement me!
10353 return RETURN_ERR;
10354}
10355
10356INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10357{
10358 return RETURN_OK;
10359}
10360
10361INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10362{
10363 // TODO Implement me!
10364 return RETURN_ERR;
10365}
10366
10367INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10368{
10369 // TODO API refrence Implementaion is present on RPI hal
10370 return RETURN_ERR;
10371}
10372
10373INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10374{
developera5005b62022-09-13 15:43:35 +080010375 char cmd[128]={'\0'};
10376 char buf[128]={'\0'};
10377 char *support;
10378 int maximum_tx = 0, current_tx = 0;
10379
10380 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10381 if(txpwr_pcntg == NULL)
10382 return RETURN_ERR;
10383
10384 // Get the maximum tx power of the device
10385 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10386 _syscmd(cmd, buf, sizeof(buf));
10387 maximum_tx = strtol(buf, NULL, 10);
10388
10389 // Get the current tx power
10390 memset(cmd, 0, sizeof(cmd));
10391 memset(buf, 0, sizeof(buf));
10392 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10393 _syscmd(cmd, buf, sizeof(buf));
10394 current_tx = strtol(buf, NULL, 10);
10395
10396 // Get the power supported list and find the current power percentage in supported list
10397 memset(buf, 0, sizeof(buf));
10398 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10399 support = strtok(buf, ",");
10400 while(true)
10401 {
10402 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10403 *txpwr_pcntg = 0;
10404 wifi_dbg_printf("current power is not in supported list\n");
10405 return RETURN_ERR;
10406 }
10407 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10408 if (tmp == current_tx) {
10409 *txpwr_pcntg = strtol(support, NULL, 10);
10410 break;
10411 }
10412 support = strtok(NULL, ",");
10413 }
10414 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010415 return RETURN_OK;
10416}
10417
10418INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10419{
developer58599c22022-09-13 16:40:34 +080010420 // TODO precac feature.
10421 struct params params = {0};
10422 char config_file[128] = {0};
10423
10424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10425
10426 params.name = "enable_background_radar";
10427 params.value = enable?"1":"0";
10428 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10429 wifi_hostapdWrite(config_file, &params, 1);
10430 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10431
10432 /* TODO precac feature */
10433
10434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10435 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010436}
10437
10438INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10439{
developer58599c22022-09-13 16:40:34 +080010440 char config_file[128] = {0};
10441 char buf[64] = {0};
10442
10443 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10444 if (NULL == enable || NULL == precac)
10445 return RETURN_ERR;
10446
10447 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10448 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10449 if (strncmp(enable, "1", 1) == 0)
10450 *enable = true;
10451 else
10452 *enable = false;
10453
10454 /* TODO precac feature */
10455
10456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10457 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010458}
10459
10460INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10461{
developer58599c22022-09-13 16:40:34 +080010462 *supported = TRUE;
10463 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010464}
10465
developer3e6b1692022-09-30 18:04:05 +080010466INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10467{
10468 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10469 struct params params = {0};
10470 char config_file[64] = {0};
10471 char buf[64] = {0};
10472 unsigned int set_mu_type = 0;
10473 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10474
10475 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10476 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10477
10478 if (strlen(buf) > 0)
10479 set_mu_type = strtol(buf, NULL, 10);
10480
10481 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10482 set_mu_type &= ~0x05; // unset bit 0, 2
10483 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10484 set_mu_type |= 0x01;
10485 set_mu_type &= ~0x04;
10486 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10487 set_mu_type &= ~0x01;
10488 set_mu_type |= 0x04;
10489 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10490 set_mu_type |= 0x05; // set bit 0, 2
10491 }
10492
10493 params.name = "hemu_onoff";
10494 sprintf(buf, "%u", set_mu_type);
10495 params.value = buf;
10496 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10497 wifi_hostapdWrite(config_file, &params, 1);
10498 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10499
10500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10501 return RETURN_OK;
10502}
10503
10504INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10505{
10506 struct params params={0};
10507 char config_file[64] = {0};
10508 char buf[64] = {0};
10509 unsigned int get_mu_type = 0;
10510
10511 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10512
10513 if (mu_type == NULL)
10514 return RETURN_ERR;
10515
10516 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10517 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10518 get_mu_type = strtol(buf, NULL, 10);
10519
10520 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10521 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10522 else if (get_mu_type & 0x04)
10523 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10524 else if (get_mu_type & 0x01)
10525 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10526 else
10527 *mu_type = WIFI_DL_MU_TYPE_NONE;
10528
10529 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10530 return RETURN_OK;
10531}
10532
10533INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10534{
10535 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10536 struct params params={0};
10537 char config_file[64] = {0};
10538 char buf[64] = {0};
10539 unsigned int set_mu_type = 0;
10540 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10541
10542 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10543 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10544
10545 if (strlen(buf) > 0)
10546 set_mu_type = strtol(buf, NULL, 10);
10547
10548 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10549 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10550 set_mu_type &= ~0x0a;
10551 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10552 set_mu_type |= 0x02;
10553 set_mu_type &= ~0x08;
10554 }
10555
10556 params.name = "hemu_onoff";
10557 sprintf(buf, "%u", set_mu_type);
10558 params.value = buf;
10559 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10560 wifi_hostapdWrite(config_file, &params, 1);
10561 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10562
10563 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10564 return RETURN_OK;
10565}
10566
10567INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10568{
10569 struct params params={0};
10570 char config_file[64] = {0};
10571 char buf[64] = {0};
10572 unsigned int get_mu_type = 0;
10573
10574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10575
10576 if (mu_type == NULL)
10577 return RETURN_ERR;
10578
10579 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10580 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10581
10582 get_mu_type = strtol(buf, NULL, 10);
10583 if (get_mu_type & 0x02)
10584 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10585 else
10586 *mu_type = WIFI_DL_MU_TYPE_NONE;
10587
10588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10589 return RETURN_OK;
10590}
10591
10592
developer454b9462022-09-13 15:29:16 +080010593INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10594{
10595 char cmd[128] = {0};
10596 char buf[64] = {0};
10597 char band_str[8] = {0};
10598 char GI[8] = {0};
10599 int tmp = 0;
10600 BOOL ax_mode = FALSE;
10601 BOOL short_GI = FALSE;
10602 FILE *f = NULL;
10603 wifi_band band;
10604
10605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10606
10607 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
10608 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10609 return RETURN_ERR;
10610 }
10611 if (strstr(buf, "ax") != NULL)
10612 ax_mode = TRUE;
10613
10614 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
10615 short_GI = TRUE;
10616 strcpy(GI, "0.4");
10617 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
10618 strcpy(GI, "1.6");
10619 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
10620 strcpy(GI, "3.2");
10621 else // default
10622 strcpy(GI, "0.8");
10623
10624 band = wifi_index_to_band(radio_index);
10625 if (band == band_2_4)
10626 strcpy(band_str, "2.4");
10627 else if (band == band_5)
10628 strcpy(band_str, "5");
10629 else if (band == band_6)
10630 strcpy(band_str, "6");
10631 else {
10632 wifi_dbg_printf("%s: invalid band\n");
10633 return RETURN_ERR;
10634 }
10635
10636 if (ax_mode == TRUE)
10637 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
10638 else
10639 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
10640 _syscmd(cmd, buf, sizeof(buf));
10641
10642 // Record GI for get GI function
10643 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10644 f = fopen(buf, "w");
10645 if (f != NULL) {
10646 fprintf(f, "%s", GI);
10647 }
10648 fclose(f);
10649 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10650 return RETURN_OK;
10651}
10652
10653INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10654{
10655 char buf[32] = {0};
10656 char cmd[64] = {0};
10657
10658 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10659
10660 if (guard_interval == NULL)
10661 return RETURN_ERR;
10662
10663 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10664 _syscmd(cmd, buf, sizeof(buf));
10665
10666 if (strncmp(buf, "0.4", 3) == 0)
10667 *guard_interval = wifi_guard_interval_400;
10668 else if (strncmp(buf, "0.8", 3) == 0)
10669 *guard_interval = wifi_guard_interval_800;
10670 else if (strncmp(buf, "1.6", 3) == 0)
10671 *guard_interval = wifi_guard_interval_1600;
10672 else if (strncmp(buf, "3.2", 3) == 0)
10673 *guard_interval = wifi_guard_interval_3200;
10674 else
10675 *guard_interval = wifi_guard_interval_auto;
10676
10677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10678 return RETURN_OK;
10679}
10680
developer3cc61d12022-09-13 16:36:05 +080010681INT wifi_setBSSColor(INT radio_index, UCHAR color)
10682{
10683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10684 struct params params = {0};
10685 char config_file[128] = {0};
10686 char bss_color[4] ={0};
10687
10688 params.name = "he_bss_color";
10689 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10690 params.value = bss_color;
10691 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10692 wifi_hostapdWrite(config_file, &params, 1);
10693 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10694
10695 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10696 return RETURN_OK;
10697}
10698
10699INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10700{
10701 char config_file[128] = {0};
10702 char buf[64] = {0};
10703 char temp_output[128] = {'\0'};
10704
10705 wifi_dbg_printf("\nFunc=%s\n", __func__);
10706 if (NULL == color)
10707 return RETURN_ERR;
10708
10709 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10710 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10711
10712 if(strlen(buf) > 0) {
10713 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10714 } else {
10715 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10716 }
10717
10718 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10719 wifi_dbg_printf("\noutput_string=%s\n", color);
10720
10721 return RETURN_OK;
10722}
10723
developer06a01d92022-09-07 16:32:39 +080010724/* multi-psk support */
10725INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10726{
10727 char cmd[256];
10728
10729 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10730 AP_PREFIX,
10731 apIndex,
10732 mac[0],
10733 mac[1],
10734 mac[2],
10735 mac[3],
10736 mac[4],
10737 mac[5]
10738 );
10739 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10740 _syscmd(cmd, key->wifi_keyId, 64);
10741
10742
10743 return RETURN_OK;
10744}
10745
10746INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10747{
10748 FILE *fd = NULL;
10749 char fname[100];
10750 char cmd[128] = {0};
10751 char out[64] = {0};
10752 wifi_key_multi_psk_t * key = NULL;
10753 if(keysNumber < 0)
10754 return RETURN_ERR;
10755
10756 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10757 fd = fopen(fname, "w");
10758 if (!fd) {
10759 return RETURN_ERR;
10760 }
10761 key= (wifi_key_multi_psk_t *) keys;
10762 for(int i=0; i<keysNumber; ++i, key++) {
10763 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10764 }
10765 fclose(fd);
10766
10767 //reload file
10768 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10769 _syscmd(cmd, out, 64);
10770 return RETURN_OK;
10771}
10772
10773INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10774{
10775 FILE *fd = NULL;
10776 char fname[100];
10777 char * line = NULL;
10778 char * pos = NULL;
10779 size_t len = 0;
10780 ssize_t read = 0;
10781 INT ret = RETURN_OK;
10782 wifi_key_multi_psk_t *keys_it = NULL;
10783
10784 if (keysNumber < 1) {
10785 return RETURN_ERR;
10786 }
10787
10788 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10789 fd = fopen(fname, "r");
10790 if (!fd) {
10791 return RETURN_ERR;
10792 }
10793
10794 if (keys == NULL) {
10795 ret = RETURN_ERR;
10796 goto close;
10797 }
10798
10799 keys_it = keys;
10800 while ((read = getline(&line, &len, fd)) != -1) {
10801 //Strip trailing new line if present
10802 if (read > 0 && line[read-1] == '\n') {
10803 line[read-1] = '\0';
10804 }
10805
10806 if(strcmp(line,"keyid=")) {
10807 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10808 if (!(pos = index(line, ' '))) {
10809 ret = RETURN_ERR;
10810 goto close;
10811 }
10812 pos++;
10813 //Here should be 00:00:00:00:00:00
10814 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10815 printf("Not supported MAC: %s\n", pos);
10816 }
10817 if (!(pos = index(pos, ' '))) {
10818 ret = RETURN_ERR;
10819 goto close;
10820 }
10821 pos++;
10822
10823 //The rest is PSK
10824 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10825 keys_it++;
10826
10827 if(--keysNumber <= 0)
10828 break;
10829 }
10830 }
10831
10832close:
10833 free(line);
10834 fclose(fd);
10835 return ret;
10836}
10837/* end of multi-psk support */
10838
10839INT wifi_setNeighborReports(UINT apIndex,
10840 UINT numNeighborReports,
10841 wifi_NeighborReport_t *neighborReports)
10842{
10843 char cmd[256] = { 0 };
10844 char hex_bssid[13] = { 0 };
10845 char bssid[18] = { 0 };
10846 char nr[256] = { 0 };
10847 char ssid[256];
10848 char hex_ssid[256];
10849 INT ret;
10850
10851 /*rmeove all neighbors*/
10852 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10853 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);
10854 system(cmd);
10855
10856 for(unsigned int i = 0; i < numNeighborReports; i++)
10857 {
10858 memset(ssid, 0, sizeof(ssid));
10859 ret = wifi_getSSIDName(apIndex, ssid);
10860 if (ret != RETURN_OK)
10861 return RETURN_ERR;
10862
10863 memset(hex_ssid, 0, sizeof(hex_ssid));
10864 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10865 sprintf(hex_ssid + k,"%02x", ssid[j]);
10866
10867 snprintf(hex_bssid, sizeof(hex_bssid),
10868 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10869 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10870 snprintf(bssid, sizeof(bssid),
10871 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10872 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10873
10874 snprintf(nr, sizeof(nr),
10875 "%s" // bssid
10876 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10877 "%02hhx" // operclass
10878 "%02hhx" // channel
10879 "%02hhx", // phy_mode
10880 hex_bssid,
10881 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10882 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10883 neighborReports[i].opClass,
10884 neighborReports[i].channel,
10885 neighborReports[i].phyTable);
10886
10887 snprintf(cmd, sizeof(cmd),
10888 "hostapd_cli set_neighbor "
10889 "%s " // bssid
10890 "ssid=%s " // ssid
10891 "nr=%s " // nr
10892 "-i %s%d",
10893 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10894
10895 if (WEXITSTATUS(system(cmd)) != 0)
10896 {
10897 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10898 }
10899 }
10900
10901 return RETURN_OK;
10902}
10903
10904INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10905{
10906 return RETURN_OK;
10907}
10908
10909#ifdef _WIFI_HAL_TEST_
10910int main(int argc,char **argv)
10911{
10912 int index;
10913 INT ret=0;
10914 char buf[1024]="";
10915
10916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10917 if(argc<3)
10918 {
10919 if(argc==2)
10920 {
10921 if(!strcmp(argv[1], "init"))
10922 return wifi_init();
10923 if(!strcmp(argv[1], "reset"))
10924 return wifi_reset();
10925 if(!strcmp(argv[1], "wifi_getHalVersion"))
10926 {
10927 char buffer[64];
10928 if(wifi_getHalVersion(buffer)==RETURN_OK)
10929 printf("Version: %s\n", buffer);
10930 else
10931 printf("Error in wifi_getHalVersion\n");
10932 return RETURN_OK;
10933 }
10934 }
10935 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10936 exit(-1);
10937 }
10938
10939 index = atoi(argv[2]);
10940 if(strstr(argv[1], "wifi_getApName")!=NULL)
10941 {
10942 wifi_getApName(index,buf);
10943 printf("Ap name is %s \n",buf);
10944 return 0;
10945 }
10946 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10947 {
10948 BOOL b = FALSE;
10949 BOOL *output_bool = &b;
10950 wifi_getRadioAutoChannelEnable(index,output_bool);
10951 printf("Channel enabled = %d \n",b);
10952 return 0;
10953 }
10954 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10955 {
10956 wifi_getApWpaEncryptionMode(index,buf);
10957 printf("encryption enabled = %s\n",buf);
10958 return 0;
10959 }
10960 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10961 {
10962 BOOL b = FALSE;
10963 BOOL *output_bool = &b;
10964 wifi_getApSsidAdvertisementEnable(index,output_bool);
10965 printf("advertisment enabled = %d\n",b);
10966 return 0;
10967 }
10968 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10969 {
10970 if(argc <= 3 )
10971 {
10972 printf("Insufficient arguments \n");
10973 exit(-1);
10974 }
10975
10976 char sta[20] = {'\0'};
10977 ULLONG handle= 0;
10978 strcpy(sta,argv[3]);
10979 mac_address_t st;
10980 mac_addr_aton(st,sta);
10981
10982 wifi_associated_dev_tid_stats_t tid_stats;
10983 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10984 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10985 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);
10986 }
10987
10988 if(strstr(argv[1], "getApEnable")!=NULL) {
10989 BOOL enable;
10990 ret=wifi_getApEnable(index, &enable);
10991 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10992 }
10993 else if(strstr(argv[1], "setApEnable")!=NULL) {
10994 BOOL enable = atoi(argv[3]);
10995 ret=wifi_setApEnable(index, enable);
10996 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10997 }
10998 else if(strstr(argv[1], "getApStatus")!=NULL) {
10999 char status[64];
11000 ret=wifi_getApStatus(index, status);
11001 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11002 }
11003 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11004 {
11005 wifi_getSSIDNameStatus(index,buf);
11006 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11007 return 0;
11008 }
11009 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11010 wifi_ssidTrafficStats2_t stats={0};
11011 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11012 printf("%s %d: returns %d\n", argv[1], index, ret);
11013 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11014 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11015 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11016 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11017 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11018 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11019 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11020 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11021 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11022 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11023 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11024 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11025 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11026 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11027 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11028 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11029 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11030 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11031 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11032 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11033 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11034 }
11035 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11036 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11037 UINT array_size=0;
11038 UINT i=0;
11039 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11040 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11041 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11042 printf(" neighbor %d:\n", i);
11043 printf(" ap_SSID =%s\n", pt->ap_SSID);
11044 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11045 printf(" ap_Mode =%s\n", pt->ap_Mode);
11046 printf(" ap_Channel =%d\n", pt->ap_Channel);
11047 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11048 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11049 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11050 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11051 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11052 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11053 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11054 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11055 printf(" ap_Noise =%d\n", pt->ap_Noise);
11056 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11057 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11058 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11059 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11060 }
11061 if(neighbor_ap_array)
11062 free(neighbor_ap_array); //make sure to free the list
11063 }
11064 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11065 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11066 UINT array_size=0;
11067 UINT i=0;
11068 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11069 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11070 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11071 printf(" associated_dev %d:\n", i);
11072 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11073 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11074 printf(" cli_SNR =%d\n", pt->cli_SNR);
11075 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11076 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11077 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11078 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11079 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11080 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11081 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11082 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11083 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11084 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11085 }
11086 if(associated_dev_array)
11087 free(associated_dev_array); //make sure to free the list
11088 }
11089
11090 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11091 {
11092#define MAX_ARRAY_SIZE 64
11093 int i, array_size;
11094 char *p, *ch_str;
11095 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11096
11097 if(argc != 5)
11098 {
11099 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11100 exit(-1);
11101 }
11102 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11103
11104 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11105 {
11106 strtok_r(ch_str, ",", &p);
11107 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11108 }
11109 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11110 if(!array_size)
11111 array_size=1;//Need to print current channel statistics
11112 for(i=0; i<array_size; i++)
11113 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11114 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11115 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11116 input_output_channelStats_array[i].ch_number,\
11117 input_output_channelStats_array[i].ch_noise,\
11118 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11119 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11120 input_output_channelStats_array[i].ch_utilization_busy,\
11121 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11122 input_output_channelStats_array[i].ch_utilization_total);
11123 }
11124
11125 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11126 {
11127 if(argc <= 3 )
11128 {
11129 printf("Insufficient arguments \n");
11130 exit(-1);
11131 }
11132 char mac_addr[20] = {'\0'};
11133 wifi_device_t output_struct;
11134 int dev_index = atoi(argv[3]);
11135
11136 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11137 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11138 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);
11139 }
11140
11141 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11142 {
11143 if (argc <= 3)
11144 {
11145 printf("Insufficient arguments\n");
11146 exit(-1);
11147 }
11148 char args[256];
11149 wifi_NeighborReport_t *neighborReports;
11150
11151 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11152 if (!neighborReports)
11153 {
11154 printf("Failed to allocate memory");
11155 exit(-1);
11156 }
11157
11158 for (int i = 3; i < argc; ++i)
11159 {
11160 char *val;
11161 int j = 0;
11162 memset(args, 0, sizeof(args));
11163 strncpy(args, argv[i], sizeof(args));
11164 val = strtok(args, ";");
11165 while (val != NULL)
11166 {
11167 if (j == 0)
11168 {
11169 mac_addr_aton(neighborReports[i - 3].bssid, val);
11170 } else if (j == 1)
11171 {
11172 neighborReports[i - 3].info = strtol(val, NULL, 16);
11173 } else if (j == 2)
11174 {
11175 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11176 } else if (j == 3)
11177 {
11178 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11179 } else if (j == 4)
11180 {
11181 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11182 } else {
11183 printf("Insufficient arguments]n\n");
11184 exit(-1);
11185 }
11186 val = strtok(NULL, ";");
11187 j++;
11188 }
11189 }
11190
11191 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11192 if (ret != RETURN_OK)
11193 {
11194 printf("wifi_setNeighborReports ret = %d", ret);
11195 exit(-1);
11196 }
11197 }
11198 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11199 {
11200 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11201 printf("%s.\n", buf);
11202 else
11203 printf("Error returned\n");
11204 }
11205 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11206 {
11207 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11208 printf("%s.\n", buf);
11209 else
11210 printf("Error returned\n");
11211 }
11212 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11213 {
11214 if (argc <= 2)
11215 {
11216 printf("Insufficient arguments\n");
11217 exit(-1);
11218 }
11219 char buf[64]= {'\0'};
11220 wifi_getRadioOperatingChannelBandwidth(index,buf);
11221 printf("Current bandwidth is %s \n",buf);
11222 return 0;
11223 }
11224 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11225 {
11226 if (argc <= 5)
11227 {
11228 printf("Insufficient arguments\n");
11229 exit(-1);
11230 }
11231 UINT channel = atoi(argv[3]);
11232 UINT width = atoi(argv[4]);
11233 UINT beacon = atoi(argv[5]);
11234 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11235 printf("Result = %d", ret);
11236 }
11237
11238 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11239 return 0;
11240}
11241
11242#endif
11243
11244#ifdef WIFI_HAL_VERSION_3
11245
developer1e5aa162022-09-13 16:06:24 +080011246INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11247{
11248 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11249 if (bitMap & WIFI_BITRATE_1MBPS)
11250 strcat(BasicRate, "1,");
11251 if (bitMap & WIFI_BITRATE_2MBPS)
11252 strcat(BasicRate, "2,");
11253 if (bitMap & WIFI_BITRATE_5_5MBPS)
11254 strcat(BasicRate, "5.5,");
11255 if (bitMap & WIFI_BITRATE_6MBPS)
11256 strcat(BasicRate, "6,");
11257 if (bitMap & WIFI_BITRATE_9MBPS)
11258 strcat(BasicRate, "9,");
11259 if (bitMap & WIFI_BITRATE_11MBPS)
11260 strcat(BasicRate, "11,");
11261 if (bitMap & WIFI_BITRATE_12MBPS)
11262 strcat(BasicRate, "12,");
11263 if (bitMap & WIFI_BITRATE_18MBPS)
11264 strcat(BasicRate, "18,");
11265 if (bitMap & WIFI_BITRATE_24MBPS)
11266 strcat(BasicRate, "24,");
11267 if (bitMap & WIFI_BITRATE_36MBPS)
11268 strcat(BasicRate, "36,");
11269 if (bitMap & WIFI_BITRATE_48MBPS)
11270 strcat(BasicRate, "48,");
11271 if (bitMap & WIFI_BITRATE_54MBPS)
11272 strcat(BasicRate, "54,");
11273 if (strlen(BasicRate) != 0) // remove last comma
11274 BasicRate[strlen(BasicRate) - 1] = '\0';
11275 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11276 return RETURN_OK;
11277}
11278
11279INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11280{
11281 UINT BitMap = 0;
11282 char *rate;
11283
11284 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11285 rate = strtok(BasicRatesList, ",");
11286 while(rate != NULL)
11287 {
11288 if (strcmp(rate, "1") == 0)
11289 BitMap |= WIFI_BITRATE_1MBPS;
11290 else if (strcmp(rate, "2") == 0)
11291 BitMap |= WIFI_BITRATE_2MBPS;
11292 else if (strcmp(rate, "5.5") == 0)
11293 BitMap |= WIFI_BITRATE_5_5MBPS;
11294 else if (strcmp(rate, "6") == 0)
11295 BitMap |= WIFI_BITRATE_6MBPS;
11296 else if (strcmp(rate, "9") == 0)
11297 BitMap |= WIFI_BITRATE_9MBPS;
11298 else if (strcmp(rate, "11") == 0)
11299 BitMap |= WIFI_BITRATE_11MBPS;
11300 else if (strcmp(rate, "12") == 0)
11301 BitMap |= WIFI_BITRATE_12MBPS;
11302 else if (strcmp(rate, "18") == 0)
11303 BitMap |= WIFI_BITRATE_18MBPS;
11304 else if (strcmp(rate, "24") == 0)
11305 BitMap |= WIFI_BITRATE_24MBPS;
11306 else if (strcmp(rate, "36") == 0)
11307 BitMap |= WIFI_BITRATE_36MBPS;
11308 else if (strcmp(rate, "48") == 0)
11309 BitMap |= WIFI_BITRATE_48MBPS;
11310 else if (strcmp(rate, "54") == 0)
11311 BitMap |= WIFI_BITRATE_54MBPS;
11312 rate = strtok(NULL, ",");
11313 }
11314 *basicRateBitMap = BitMap;
11315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11316 return RETURN_OK;
11317}
11318
11319// 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 +080011320INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11321{
developer1e5aa162022-09-13 16:06:24 +080011322 char buf[128] = {0};
11323 char cmd[128] = {0};
11324 char config_file[64] = {0};
11325 int bandwidth;
11326 int set_mode;
11327 wifi_radio_operationParam_t current_param;
11328
11329 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11330
11331 multiple_set = TRUE;
11332 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11333 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11334 return RETURN_ERR;
11335 }
11336 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11337 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11338 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11339 return RETURN_ERR;
11340 }
11341 }
11342 if (current_param.channelWidth != operationParam->channelWidth || (current_param.channel != operationParam->channel && !operationParam->autoChannelEnabled)) {
11343 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11344 bandwidth = 20;
11345 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11346 bandwidth = 40;
11347 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11348 bandwidth = 80;
11349 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11350 bandwidth = 160;
11351 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11352 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11353 return RETURN_ERR;
11354 }
11355 }
11356 if (current_param.variant != operationParam->variant) {
11357 // Two different definition bit map, so need to check every bit.
11358 if (operationParam->variant & WIFI_80211_VARIANT_A)
11359 set_mode |= WIFI_MODE_A;
11360 if (operationParam->variant & WIFI_80211_VARIANT_B)
11361 set_mode |= WIFI_MODE_B;
11362 if (operationParam->variant & WIFI_80211_VARIANT_G)
11363 set_mode |= WIFI_MODE_G;
11364 if (operationParam->variant & WIFI_80211_VARIANT_N)
11365 set_mode |= WIFI_MODE_N;
11366 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11367 set_mode |= WIFI_MODE_AC;
11368 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11369 set_mode |= WIFI_MODE_AX;
11370 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11371 memset(buf, 0, sizeof(buf));
11372 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11373 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11374 return RETURN_ERR;
11375 }
11376 }
11377 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11378 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11379 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11380 return RETURN_ERR;
11381 }
11382 }
11383 if (current_param.beaconInterval != operationParam->beaconInterval) {
11384 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11385 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11386 return RETURN_ERR;
11387 }
11388 }
11389 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11390 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11391 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11392 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11393 return RETURN_ERR;
11394 }
11395 }
11396 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11397 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11398 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11399 return RETURN_ERR;
11400 }
11401 }
11402 if (current_param.guardInterval != operationParam->guardInterval) {
11403 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11404 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11405 return RETURN_ERR;
11406 }
11407 }
11408 if (current_param.transmitPower != operationParam->transmitPower) {
11409 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11410 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11411 return RETURN_ERR;
11412 }
11413 }
11414 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11415 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11416 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11417 return RETURN_ERR;
11418 }
11419 }
11420 if (current_param.obssCoex != operationParam->obssCoex) {
11421 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11422 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11423 return RETURN_ERR;
11424 }
11425 }
11426 if (current_param.stbcEnable != operationParam->stbcEnable) {
11427 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11428 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11429 return RETURN_ERR;
11430 }
11431 }
11432 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11433 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11434 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11435 return RETURN_ERR;
11436 }
11437 }
11438
11439 // if enable is true, then restart the radio
11440 wifi_setRadioEnable(index, FALSE);
11441 if (operationParam->enable == TRUE)
11442 wifi_setRadioEnable(index, TRUE);
11443 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11444
developer06a01d92022-09-07 16:32:39 +080011445 return RETURN_OK;
11446}
11447
11448INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11449{
developer1e5aa162022-09-13 16:06:24 +080011450 char band[64] = {0};
11451 char buf[256] = {0};
11452 char config_file[64] = {0};
11453 char cmd[128] = {0};
11454 int ret = RETURN_ERR;
11455 int mode = 0;
11456 ULONG channel = 0;
11457 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011458
11459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11460 printf("Entering %s index = %d\n", __func__, (int)index);
11461
developer1e5aa162022-09-13 16:06:24 +080011462 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11463 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11464 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011465 {
developer1e5aa162022-09-13 16:06:24 +080011466 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011467 return RETURN_ERR;
11468 }
11469 operationParam->enable = enabled;
11470
11471 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011472 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011473 {
developer1e5aa162022-09-13 16:06:24 +080011474 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011475 return RETURN_ERR;
11476 }
11477
11478 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011479 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011480 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011481 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011482 else if (!strcmp(band, "6GHz"))
11483 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011484 else
11485 {
developer1e5aa162022-09-13 16:06:24 +080011486 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011487 band);
11488 }
11489
developer1e5aa162022-09-13 16:06:24 +080011490 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11491 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11492 operationParam->channel = 0;
11493 operationParam->autoChannelEnabled = TRUE;
11494 } else {
11495 operationParam->channel = strtol(buf, NULL, 10);
11496 operationParam->autoChannelEnabled = FALSE;
11497 }
11498
developer06a01d92022-09-07 16:32:39 +080011499 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011500 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11501 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11502 return RETURN_ERR;
11503 }
developer06a01d92022-09-07 16:32:39 +080011504 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11505 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11506 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer1e5aa162022-09-13 16:06:24 +080011507 else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11508 else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011509 else
11510 {
developer1e5aa162022-09-13 16:06:24 +080011511 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11512 return false;
developer06a01d92022-09-07 16:32:39 +080011513 }
11514
developer1e5aa162022-09-13 16:06:24 +080011515 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11516 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11517 return RETURN_ERR;
11518 }
11519 // Two different definition bit map, so need to check every bit.
11520 if (mode & WIFI_MODE_A)
11521 operationParam->variant |= WIFI_80211_VARIANT_A;
11522 if (mode & WIFI_MODE_B)
11523 operationParam->variant |= WIFI_80211_VARIANT_B;
11524 if (mode & WIFI_MODE_G)
11525 operationParam->variant |= WIFI_80211_VARIANT_G;
11526 if (mode & WIFI_MODE_N)
11527 operationParam->variant |= WIFI_80211_VARIANT_N;
11528 if (mode & WIFI_MODE_AC)
11529 operationParam->variant |= WIFI_80211_VARIANT_AC;
11530 if (mode & WIFI_MODE_AX)
11531 operationParam->variant |= WIFI_80211_VARIANT_AX;
11532 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11533 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11534 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011535 }
developer1e5aa162022-09-13 16:06:24 +080011536 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11537 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11538 return RETURN_ERR;
11539 }
11540 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11541 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11542 return RETURN_ERR;
11543 }
developer06a01d92022-09-07 16:32:39 +080011544
developer1e5aa162022-09-13 16:06:24 +080011545 memset(buf, 0, sizeof(buf));
11546 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11547 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11548 return RETURN_ERR;
11549 }
11550 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11551
11552 memset(buf, 0, sizeof(buf));
11553 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11554 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11555 return RETURN_ERR;
11556 }
11557 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11558
11559 memset(buf, 0, sizeof(buf));
11560 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11561 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11562
11563 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11564 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11565 return RETURN_ERR;
11566 }
11567 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11568 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11569 return RETURN_ERR;
11570 }
11571
11572 memset(buf, 0, sizeof(buf));
11573 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11574 if (strcmp(buf, "-1") == 0) {
11575 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11576 operationParam->ctsProtection = FALSE;
11577 } else {
11578 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11579 operationParam->ctsProtection = TRUE;
11580 }
11581
11582 memset(buf, 0, sizeof(buf));
11583 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11584 if (strcmp(buf, "0") == 0)
11585 operationParam->obssCoex = FALSE;
11586 else
11587 operationParam->obssCoex = TRUE;
11588
11589 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11590 _syscmd(cmd, buf, sizeof(buf));
11591 if (strlen(buf) != 0)
11592 operationParam->stbcEnable = TRUE;
11593 else
11594 operationParam->stbcEnable = FALSE;
11595
11596 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11597 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11598 return RETURN_ERR;
11599 }
11600
11601 // Below value is hardcoded
11602
11603 operationParam->numSecondaryChannels = 0;
11604 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11605 operationParam->channelSecondary[i] = 0;
11606 }
11607 operationParam->csa_beacon_count = 15;
11608 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011609
11610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11611 return RETURN_OK;
11612}
11613
11614static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11615{
11616 if (radioIndex != 0 && radioIndex != 1)
11617 {
11618 printf("%s: Wrong radio index (%d)\n", __func__, index);
11619 return -1;
11620 }
11621
11622 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
11623 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
11624
11625 return (arrayIndex * 2) + radioIndex;
11626}
11627
11628INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11629{
11630 INT ret;
11631 int i;
11632 BOOL enabled = false;
11633 char buf[256];
11634 wifi_secur_list *secur_item;
11635 int vap_index;
11636 INT mode;
11637 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
11638
11639 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11640 printf("Entering %s index = %d\n", __func__, (int)index);
11641
11642 map->vap_array[index].radio_index = index;
11643 for (i = 0; i < 5; i++)
11644 {
11645 vap_index = array_index_to_vap_index(index, i);
11646 if (vap_index < 0)
11647 {
11648 return RETURN_ERR;
11649 }
11650
11651 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
11652
11653 map->vap_array[i].vap_index = vap_index;
11654
11655 memset(buf, 0, sizeof(buf));
11656 wifi_getApName(vap_index, buf); // XXX: error handling
11657 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
11658
11659 ret = wifi_getSSIDEnable(vap_index, &enabled);
11660 if (ret != RETURN_OK)
11661 {
11662 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
11663 return RETURN_ERR;
11664 }
11665 map->vap_array[i].u.bss_info.enabled = enabled;
11666
11667 memset(buf, 0, sizeof(buf));
11668 wifi_getBaseBSSID(vap_index, buf);
11669 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11670 &map->vap_array[i].u.bss_info.bssid[0],
11671 &map->vap_array[i].u.bss_info.bssid[1],
11672 &map->vap_array[i].u.bss_info.bssid[2],
11673 &map->vap_array[i].u.bss_info.bssid[3],
11674 &map->vap_array[i].u.bss_info.bssid[4],
11675 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
11676
11677 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
11678 map->vap_array[i].u.bss_info.showSsid = enabled;
11679
11680 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
11681 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
11682 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
11683
11684 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11685 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
11686
11687 memset(buf, 0, sizeof(buf));
11688 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
11689 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
11690
11691 wifi_getApSecurityModeEnabled(vap_index, buf);
11692
11693 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
11694 {
11695 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
11696 return RETURN_ERR;
11697 }
11698 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
11699
11700 memset(buf, 0, sizeof(buf));
11701 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
11702 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);
11703
11704 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
11705 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
11706
11707 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
11708 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
11709
11710 wifi_getApIsolationEnable(vap_index, &enabled);
11711 map->vap_array[i].u.bss_info.isolation = enabled;
11712 }
11713 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11714 return RETURN_OK;
11715}
11716
11717INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11718{
11719 unsigned int i;
11720 wifi_vap_info_t *vap_info = NULL;
11721 int acl_mode;
11722 char *sec_str = NULL;
11723
11724 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11725 printf("Entering %s index = %d\n", __func__, (int)index);
11726 for (i = 0; i < map->num_vaps; i++)
11727 {
11728 vap_info = &map->vap_array[i];
11729 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11730
11731 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11732 else
11733 {
11734 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11735 else acl_mode = 1;
11736 }
11737 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11738 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11739 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11740
11741 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11742 if (sec_str)
11743 {
11744 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11745 }
11746 else
11747 {
11748 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11749 }
11750
11751 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11752 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11753
11754 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11755 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11756
11757 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11758
11759 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11760 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11761 }
11762 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11763 return RETURN_OK;
11764}
11765
11766int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11767{
11768 char *token, *next;
11769 const char s[2] = ",";
11770 int count =0;
11771
11772 /* get the first token */
11773 token = strtok_r(pchannels, s, &next);
11774
11775 /* walk through other tokens */
11776 while( token != NULL && count < MAX_CHANNELS) {
11777 chlistptr->channels_list[count++] = atoi(token);
11778 token = strtok_r(NULL, s, &next);
11779 }
11780
11781 return count;
11782}
11783
11784static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11785{
11786 INT status;
11787 wifi_channels_list_t *chlistp;
11788 CHAR output_string[64];
11789 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011790 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011791
11792 if(rcap == NULL)
11793 {
11794 return RETURN_ERR;
11795 }
11796
11797 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011798 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011799
developer1e5aa162022-09-13 16:06:24 +080011800 if (band == band_2_4)
11801 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11802 else if (band == band_5)
11803 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11804 else if (band == band_6)
11805 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011806
11807 chlistp = &(rcap->channel_list[0]);
11808 memset(pchannels, 0, sizeof(pchannels));
11809
11810 /* possible number of radio channels */
11811 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11812 {
11813 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11814 }
11815 /* Number of channels and list*/
11816 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11817
11818 /* autoChannelSupported */
11819 /* always ON with wifi_getRadioAutoChannelSupported */
11820 rcap->autoChannelSupported = TRUE;
11821
11822 /* DCSSupported */
11823 /* always ON with wifi_getRadioDCSSupported */
11824 rcap->DCSSupported = TRUE;
11825
11826 /* zeroDFSSupported - TBD */
11827 rcap->zeroDFSSupported = FALSE;
11828
11829 /* Supported Country List*/
11830 memset(output_string, 0, sizeof(output_string));
11831 status = wifi_getRadioCountryCode(radioIndex, output_string);
11832 if( status != 0 ) {
11833 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11834 return RETURN_ERR;
11835 } else {
11836 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11837 }
11838 if(!strcmp(output_string,"US")){
11839 rcap->countrySupported[0] = wifi_countrycode_US;
11840 rcap->countrySupported[1] = wifi_countrycode_CA;
11841 } else if (!strcmp(output_string,"CA")) {
11842 rcap->countrySupported[0] = wifi_countrycode_CA;
11843 rcap->countrySupported[1] = wifi_countrycode_US;
11844 } else {
11845 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11846 }
11847
11848 rcap->numcountrySupported = 2;
11849
11850 /* csi */
11851 rcap->csi.maxDevices = 8;
11852 rcap->csi.soudingFrameSupported = TRUE;
11853
11854 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
11855
11856 /* channelWidth - all supported bandwidths */
11857 int i=0;
11858 rcap->channelWidth[i] = 0;
11859 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11860 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11861 WIFI_CHANNELBANDWIDTH_40MHZ);
11862
11863 }
developer1e5aa162022-09-13 16:06:24 +080011864 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080011865 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11866 WIFI_CHANNELBANDWIDTH_40MHZ |
11867 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
11868 }
11869
11870
11871 /* mode - all supported variants */
11872 // rcap->mode[i] = WIFI_80211_VARIANT_H;
11873 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011874 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 +080011875 }
11876 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011877 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
11878 }
11879 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
11880 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011881 }
11882 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
11883 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
11884
11885 /* supportedBitRate - all supported bitrates */
11886 rcap->supportedBitRate[i] = 0;
11887 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11888 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11889 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
11890 }
developer1e5aa162022-09-13 16:06:24 +080011891 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080011892 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11893 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
11894 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
11895 }
11896
11897
11898 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
11899 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
11900 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
11901 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
11902 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
11903 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
11904 rcap->cipherSupported = 0;
11905 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
11906 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
11907
11908 return RETURN_OK;
11909}
11910
11911INT wifi_getHalCapability(wifi_hal_capability_t *cap)
11912{
11913 INT status, radioIndex;
11914 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
11915 int iter = 0;
11916 unsigned int j;
11917 wifi_interface_name_idex_map_t *iface_info;
11918
11919 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11920
11921 memset(cap, 0, sizeof(wifi_hal_capability_t));
11922
11923 /* version */
11924 cap->version.major = WIFI_HAL_MAJOR_VERSION;
11925 cap->version.minor = WIFI_HAL_MINOR_VERSION;
11926
11927 /* number of radios platform property */
11928 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
11929 _syscmd(cmd, output, sizeof(output));
11930 cap->wifi_prop.numRadios = atoi(output);
11931
11932 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
11933 {
11934 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
11935 if (status != 0) {
11936 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
11937 return RETURN_ERR;
11938 }
11939
11940 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
11941 {
11942 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
11943 {
11944 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
11945 return RETURN_ERR;
11946 }
11947 iface_info = &cap->wifi_prop.interface_map[iter];
11948 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
11949 iface_info->rdk_radio_index = radioIndex;
11950 memset(output, 0, sizeof(output));
11951 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
11952 {
11953 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
11954 }
11955 // TODO: bridge name
11956 // TODO: vlan id
11957 // TODO: primary
11958 iface_info->index = array_index_to_vap_index(radioIndex, j);
11959 memset(output, 0, sizeof(output));
11960 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
11961 {
11962 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
11963 }
11964 iter++;
11965 }
11966 }
11967
11968 cap->BandSteeringSupported = FALSE;
11969 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11970 return RETURN_OK;
11971}
11972
11973INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
11974{
developer587c1b62022-09-27 15:58:59 +080011975 char buf[128] = {0};
11976 char config_file[128] = {0};
11977 char password[64] = {0};
11978 char mfp[32] = {0};
11979 char wpa_mode[32] = {0};
11980 struct params params = {0};
11981
11982 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11983
11984 multiple_set = TRUE;
11985 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11986 if (security->mode == wifi_security_mode_none) {
11987 strcpy(wpa_mode, "None");
11988 } else if (security->mode == wifi_security_mode_wpa_personal)
11989 strcpy(wpa_mode, "WPA-Personal");
11990 else if (security->mode == wifi_security_mode_wpa2_personal)
11991 strcpy(wpa_mode, "WPA2-Personal");
11992 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
11993 strcpy(wpa_mode, "WPA-WPA2-Personal");
11994 else if (security->mode == wifi_security_mode_wpa_enterprise)
11995 strcpy(wpa_mode, "WPA-Enterprise");
11996 else if (security->mode == wifi_security_mode_wpa2_enterprise)
11997 strcpy(wpa_mode, "WPA2-Enterprise");
11998 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
11999 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
12000 else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
12001 strcpy(wpa_mode, "WPA3-Personal");
12002 else if (security->mode == wifi_security_mode_wpa3_enterprise)
12003 strcpy(wpa_mode, "WPA3-Enterprise");
12004
12005 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
12006
12007 strncpy(password, security->u.key.key, 63);
12008 password[63] = '\0';
12009 wifi_setApSecurityKeyPassphrase(ap_index, password);
12010
12011 if (security->mode != wifi_security_mode_none) {
12012 memset(&params, 0, sizeof(params));
12013 params.name = "wpa_pairwise";
12014 if (security->encr == wifi_encryption_tkip)
12015 params.value = "TKIP";
12016 else if (security->encr == wifi_encryption_aes)
12017 params.value = "CCMP";
12018 else if (security->encr == wifi_encryption_aes_tkip)
12019 params.value = "TKIP CCMP";
12020 wifi_hostapdWrite(config_file, &params, 1);
12021 }
12022
12023 if (security->mfp == wifi_mfp_cfg_disabled)
12024 strcpy(mfp, "Disable");
12025 else if (security->mfp == wifi_mfp_cfg_optional)
12026 strcpy(mfp, "Optional");
12027 else if (security->mfp == wifi_mfp_cfg_required)
12028 strcpy(mfp, "Required");
12029 wifi_setApSecurityMFPConfig(ap_index, mfp);
12030
12031 memset(&params, 0, sizeof(params));
12032 params.name = "transition_disable";
12033 if (security->wpa3_transition_disable == TRUE)
12034 params.value = "0x01";
12035 else
12036 params.value = "0x00";
12037 wifi_hostapdWrite(config_file, &params, 1);
12038
12039 memset(&params, 0, sizeof(params));
12040 params.name = "wpa_group_rekey";
12041 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12042 params.value = buf;
12043 wifi_hostapdWrite(config_file, &params, 1);
12044
12045 memset(&params, 0, sizeof(params));
12046 params.name = "wpa_strict_rekey";
12047 params.value = security->strict_rekey?"1":"0";
12048 wifi_hostapdWrite(config_file, &params, 1);
12049
12050 memset(&params, 0, sizeof(params));
12051 params.name = "wpa_pairwise_update_count";
12052 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12053 params.value = buf;
12054 wifi_hostapdWrite(config_file, &params, 1);
12055
12056 memset(&params, 0, sizeof(params));
12057 params.name = "disable_pmksa_caching";
12058 params.value = security->disable_pmksa_caching?"1":"0";
12059 wifi_hostapdWrite(config_file, &params, 1);
12060
12061 wifi_setApEnable(ap_index, FALSE);
12062 wifi_setApEnable(ap_index, TRUE);
12063
12064 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12065
developer06a01d92022-09-07 16:32:39 +080012066 return RETURN_OK;
12067}
12068
12069INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12070{
developer587c1b62022-09-27 15:58:59 +080012071 char buf[128] = {0};
12072 char config_file[128] = {0};
12073 int disable = 0;
12074 // struct params params = {0};
12075
12076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12077 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12078 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12079 security->mode = wifi_security_mode_none;
12080 if (strlen(buf) != 0) {
12081 if (strcmp(buf, "WPA-Personal"))
12082 security->mode = wifi_security_mode_wpa_personal;
12083 else if (strcmp(buf, "WPA2-Personal"))
12084 security->mode = wifi_security_mode_wpa2_personal;
12085 else if (strcmp(buf, "WPA-WPA2-Personal"))
12086 security->mode = wifi_security_mode_wpa_wpa2_personal;
12087 else if (strcmp(buf, "WPA-Enterprise"))
12088 security->mode = wifi_security_mode_wpa_enterprise;
12089 else if (strcmp(buf, "WPA2-Enterprise"))
12090 security->mode = wifi_security_mode_wpa2_enterprise;
12091 else if (strcmp(buf, "WPA-WPA2-Enterprise"))
12092 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
12093 else if (strcmp(buf, "WPA3-Personal"))
12094 security->mode = wifi_security_mode_wpa3_personal;
12095 else if (strcmp(buf, "WPA3-Transition"))
12096 security->mode = wifi_security_mode_wpa3_transition;
12097 else if (strcmp(buf, "WPA3-Enterprise"))
12098 security->mode = wifi_security_mode_wpa3_enterprise;
12099 }
12100
12101 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12102 if (security->mode == wifi_security_mode_none)
12103 security->encr = wifi_encryption_none;
12104 else {
12105 if (strcmp(buf, "TKIP") == 0)
12106 security->encr = wifi_encryption_tkip;
12107 else if (strcmp(buf, "CCMP") == 0)
12108 security->encr = wifi_encryption_aes;
12109 else
12110 security->encr = wifi_encryption_aes_tkip;
12111 }
12112
12113 memset(buf, 0, sizeof(buf));
12114 wifi_getApSecurityMFPConfig(ap_index, buf);
12115 if (strcmp(buf, "Disabled") == 0)
12116 security->mfp = wifi_mfp_cfg_disabled;
12117 else if (strcmp(buf, "Optional") == 0)
12118 security->mfp = wifi_mfp_cfg_optional;
12119 else if (strcmp(buf, "Required") == 0)
12120 security->mfp = wifi_mfp_cfg_required;
12121
12122 memset(buf, 0, sizeof(buf));
12123 security->wpa3_transition_disable = FALSE;
12124 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12125 disable = strtol(buf, NULL, 16);
12126 if (disable != 0)
12127 security->wpa3_transition_disable = TRUE;
12128
12129 memset(buf, 0, sizeof(buf));
12130 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12131 if (strlen(buf) == 0)
12132 security->rekey_interval = 86400;
12133 else
12134 security->rekey_interval = strtol(buf, NULL, 10);
12135
12136 memset(buf, 0, sizeof(buf));
12137 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12138 if (strlen(buf) == 0)
12139 security->strict_rekey = 1;
12140 else
12141 security->strict_rekey = strtol(buf, NULL, 10);
12142
12143 memset(buf, 0, sizeof(buf));
12144 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12145 if (strlen(buf) == 0)
12146 security->eapol_key_retries = 4;
12147 else
12148 security->eapol_key_retries = strtol(buf, NULL, 10);
12149
12150 memset(buf, 0, sizeof(buf));
12151 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12152 if (strlen(buf) == 0)
12153 security->disable_pmksa_caching = FALSE;
12154 else
12155 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12156
12157 /* TODO
12158 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12159 */
12160 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12161 security->eap_identity_req_timeout = 0;
12162 security->eap_identity_req_retries = 0;
12163 security->eap_req_timeout = 0;
12164 security->eap_req_retries = 0;
12165 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012166 return RETURN_OK;
12167}
12168
12169#endif /* WIFI_HAL_VERSION_3 */
12170
12171#ifdef WIFI_HAL_VERSION_3_PHASE2
12172INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12173{
developer13df9332022-09-27 16:53:22 +080012174 char cmd[128] = {0};
12175 char buf[128] = {0};
12176 char *mac_addr = NULL;
12177 BOOL status = FALSE;
12178 size_t len = 0;
12179
12180 if(ap_index > MAX_APS)
12181 return RETURN_ERR;
12182
12183 *output_numDevices = 0;
12184 wifi_getApEnable(ap_index, &status);
12185 if (status == FALSE)
12186 return RETURN_OK;
12187
12188 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12189 _syscmd(cmd, buf, sizeof(buf));
12190
12191 mac_addr = strtok(buf, "\n");
12192 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12193 *output_numDevices = i + 1;
12194 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12195 addr_ptr = output_deviceMacAddressArray[i];
12196 mac_addr_aton(addr_ptr, mac_addr);
12197 mac_addr = strtok(NULL, "\n");
12198 }
12199
12200 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012201}
12202#else
12203INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12204{
12205 char cmd[128];
12206 BOOL status = false;
12207
12208 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12209 return RETURN_ERR;
12210
12211 output_buf[0] = '\0';
12212
12213 wifi_getApEnable(ap_index,&status);
12214 if (!status)
12215 return RETURN_OK;
12216
12217 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12218 _syscmd(cmd, output_buf, output_buf_size);
12219
12220 return RETURN_OK;
12221}
12222#endif
developer2f513ab2022-09-13 14:26:06 +080012223
12224INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12225{
12226 char output[16]={'\0'};
12227 char config_file[MAX_BUF_SIZE] = {0};
12228
12229 if (!enable)
12230 return RETURN_ERR;
12231
12232 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12233 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12234
12235 if (strlen(output) == 0)
12236 *enable = FALSE;
12237 else if (strncmp(output, "1", 1) == 0)
12238 *enable = TRUE;
12239 else
12240 *enable = FALSE;
12241
12242 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12243 return RETURN_OK;
12244}
developer2d9c30f2022-09-13 15:06:14 +080012245
12246INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12247{
12248 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12249 return RETURN_ERR;
12250 *output_enable=TRUE;
12251 return RETURN_OK;
12252}
developerfd7d2892022-09-13 16:44:53 +080012253
12254INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12255{
12256 char cmd[128] = {0};
12257 char buf[128] = {0};
12258 char line[128] = {0};
12259 size_t len = 0;
12260 ssize_t read = 0;
12261 FILE *f = NULL;
12262 int index = 0;
12263 int exp = 0;
12264 int mantissa = 0;
12265 int duration = 0;
12266 int radio_index = 0;
12267 int max_radio_num = 0;
12268 uint twt_wake_interval = 0;
12269
12270 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12271
12272 wifi_getMaxRadioNumber(&max_radio_num);
12273 radio_index = ap_index % max_radio_num;
12274 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12275 _syscmd(cmd, buf, sizeof(buf));
12276 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12277 if (*numSessionReturned > maxNumberSessions)
12278 *numSessionReturned = maxNumberSessions;
12279 else if (*numSessionReturned < 1) {
12280 *numSessionReturned = 0;
12281 return RETURN_OK;
12282 }
12283
12284 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12285 if ((f = popen(cmd, "r")) == NULL) {
12286 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12287 return RETURN_ERR;
12288 }
12289
12290 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12291 while((read = fgets(line, sizeof(line), f)) != NULL) {
12292 char *tmp = NULL;
12293 strcpy(buf, line);
12294 tmp = strtok(buf, " ");
12295 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12296 tmp = strtok(NULL, " ");
12297 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12298 tmp = strtok(NULL, " ");
12299 if (strstr(tmp, "t")) {
12300 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12301 }
12302 if (strstr(tmp, "a")) {
12303 twtSessions[index].twtParameters.operation.announced = TRUE;
12304 }
12305 tmp = strtok(NULL, " ");
12306 exp = strtol(tmp, NULL, 10);
12307 tmp = strtok(NULL, " ");
12308 mantissa = strtol(tmp, NULL, 10);
12309 tmp = strtok(NULL, " ");
12310 duration = strtol(tmp, NULL, 10);
12311
12312 // only implicit supported
12313 twtSessions[index].twtParameters.operation.implicit = TRUE;
12314 // only individual agreement supported
12315 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12316
12317 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12318 twt_wake_interval = mantissa * (1 << exp);
12319 if (twt_wake_interval/mantissa != (1 << exp)) {
12320 // Overflow handling
12321 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12322 } else {
12323 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12324 }
12325 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12326 index++;
12327 }
12328
12329 pclose(f);
12330 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12331 return RETURN_OK;
12332}