blob: b24d39100955c00d8afe61ceb6ac657d48752c5c [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"
developer454b9462022-09-13 15:29:16 +080080
developer06a01d92022-09-07 16:32:39 +080081#define DRIVER_2GHZ "ath9k"
82#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080083#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080084
85/*
86 MAX_APS - Number of all AP available in system
87 2x Home AP
88 2x Backhaul AP
89 2x Guest AP
90 2x Secure Onboard AP
91 2x Service AP
92
93*/
94#define MAX_APS 10
95#define NUMBER_OF_RADIOS 2
96
97#ifndef AP_PREFIX
98#define AP_PREFIX "wifi"
99#endif
100
101#ifndef RADIO_PREFIX
102#define RADIO_PREFIX "wlan"
103#endif
104
105#define MAX_BUF_SIZE 128
106#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800107#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800108
109//Uncomment to enable debug logs
110//#define WIFI_DEBUG
111
112#ifdef WIFI_DEBUG
113#define wifi_dbg_printf printf
114#define WIFI_ENTRY_EXIT_DEBUG printf
115#else
116#define wifi_dbg_printf(format, args...) printf("")
117#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
118#endif
119
120#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
121#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
122#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
123#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
124#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
125#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
126#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
127#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
128#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
129#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
130
131#define HOSTAPD_HT_CAPAB_20 "[SHORT-GI-20]"
132#define HOSTAPD_HT_CAPAB_40 "[SHORT-GI-20][SHORT-GI-40]"
133
134#define BW_FNAME "/nvram/bw_file.txt"
135
136#define PS_MAX_TID 16
137
138static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
139 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
140 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
141 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
142 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
143 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
144 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
145 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
146 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
148 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
149 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
150 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
151 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
152 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
153 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
154 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
155};
156
157typedef unsigned long long u64;
158
159/* Enum to define WiFi Bands */
160typedef enum
161{
162 band_invalid = -1,
163 band_2_4 = 0,
164 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800165 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800166} wifi_band;
167
developerdb744382022-09-13 15:34:54 +0800168typedef enum {
169 WIFI_MODE_A = 0x01,
170 WIFI_MODE_B = 0x02,
171 WIFI_MODE_G = 0x04,
172 WIFI_MODE_N = 0x08,
173 WIFI_MODE_AC = 0x10,
174 WIFI_MODE_AX = 0x20,
175} wifi_ieee80211_Mode;
176
developer06a01d92022-09-07 16:32:39 +0800177#ifdef WIFI_HAL_VERSION_3
178
179// Return number of elements in array
180#ifndef ARRAY_SIZE
181#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
182#endif /* ARRAY_SIZE */
183
184#ifndef ARRAY_AND_SIZE
185#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
186#endif /* ARRAY_AND_SIZE */
187
188#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
189
190typedef struct {
191 int32_t value;
192 int32_t param;
193 intptr_t key;
194 intptr_t data;
195} wifi_secur_list;
196
197wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
198wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
199char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
200
201static wifi_secur_list map_security[] =
202{
203 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
204 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
205 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
206 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
207 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
208 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
212};
213
214wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
215{
216 wifi_secur_list *item;
217 int i;
218
219 for (item = list,i = 0;i < list_sz; item++, i++) {
220 if ((int)(item->key) == key) {
221 return item;
222 }
223 }
224
225 return NULL;
226}
227
228char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
229{
230 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
231
232 if (!item) {
233 return "";
234 }
235
236 return (char *)(item->data);
237}
238
239wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
240{
241 wifi_secur_list *item;
242 int i;
243
244 for (item = list,i = 0;i < list_sz; item++, i++) {
245 if (strcmp((char *)(item->data), str) == 0) {
246 return item;
247 }
248 }
249
250 return NULL;
251}
252#endif /* WIFI_HAL_VERSION_3 */
253
254#ifdef HAL_NETLINK_IMPL
255typedef struct {
256 int id;
257 struct nl_sock* socket;
258 struct nl_cb* cb;
259} Netlink;
260
261static int mac_addr_aton(unsigned char *mac_addr, char *arg)
262{
263 unsigned int mac_addr_int[6]={};
264 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);
265 mac_addr[0] = mac_addr_int[0];
266 mac_addr[1] = mac_addr_int[1];
267 mac_addr[2] = mac_addr_int[2];
268 mac_addr[3] = mac_addr_int[3];
269 mac_addr[4] = mac_addr_int[4];
270 mac_addr[5] = mac_addr_int[5];
271 return 0;
272}
273
274static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
275{
276 unsigned int mac_addr_int[6]={};
277 mac_addr_int[0] = arg[0];
278 mac_addr_int[1] = arg[1];
279 mac_addr_int[2] = arg[2];
280 mac_addr_int[3] = arg[3];
281 mac_addr_int[4] = arg[4];
282 mac_addr_int[5] = arg[5];
283 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]);
284 return;
285}
286
287static int ieee80211_frequency_to_channel(int freq)
288{
289 if (freq == 2484)
290 return 14;
291 else if (freq < 2484)
292 return (freq - 2407) / 5;
293 else if (freq >= 4910 && freq <= 4980)
294 return (freq - 4000) / 5;
295 else if (freq <= 45000)
296 return (freq - 5000) / 5;
297 else if (freq >= 58320 && freq <= 64800)
298 return (freq - 56160) / 2160;
299 else
300 return 0;
301}
302
303static int initSock80211(Netlink* nl) {
304 nl->socket = nl_socket_alloc();
305 if (!nl->socket) {
306 fprintf(stderr, "Failing to allocate the sock\n");
307 return -ENOMEM;
308 }
309
310 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
311
312 if (genl_connect(nl->socket)) {
313 fprintf(stderr, "Failed to connect\n");
314 nl_close(nl->socket);
315 nl_socket_free(nl->socket);
316 return -ENOLINK;
317 }
318
319 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
320 if (nl->id< 0) {
321 fprintf(stderr, "interface not found.\n");
322 nl_close(nl->socket);
323 nl_socket_free(nl->socket);
324 return -ENOENT;
325 }
326
327 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
328 if ((!nl->cb)) {
329 fprintf(stderr, "Failed to allocate netlink callback.\n");
330 nl_close(nl->socket);
331 nl_socket_free(nl->socket);
332 return ENOMEM;
333 }
334
335 return nl->id;
336}
337
338static int nlfree(Netlink *nl)
339{
340 nl_cb_put(nl->cb);
341 nl_close(nl->socket);
342 nl_socket_free(nl->socket);
343 return 0;
344}
345
346static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
347 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
348 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
349 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
350};
351
352static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
353};
354
355static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
356};
357
358typedef struct _wifi_channelStats_loc {
359 INT array_size;
360 INT ch_number;
361 BOOL ch_in_pool;
362 INT ch_noise;
363 BOOL ch_radar_noise;
364 INT ch_max_80211_rssi;
365 INT ch_non_80211_noise;
366 INT ch_utilization;
367 ULLONG ch_utilization_total;
368 ULLONG ch_utilization_busy;
369 ULLONG ch_utilization_busy_tx;
370 ULLONG ch_utilization_busy_rx;
371 ULLONG ch_utilization_busy_self;
372 ULLONG ch_utilization_busy_ext;
373} wifi_channelStats_t_loc;
374
375typedef struct wifi_device_info {
376 INT wifi_devIndex;
377 UCHAR wifi_devMacAddress[6];
378 CHAR wifi_devIPAddress[64];
379 BOOL wifi_devAssociatedDeviceAuthentiationState;
380 INT wifi_devSignalStrength;
381 INT wifi_devTxRate;
382 INT wifi_devRxRate;
383} wifi_device_info_t;
384
385#endif
386
387//For 5g Alias Interfaces
388static BOOL priv_flag = TRUE;
389static BOOL pub_flag = TRUE;
390static BOOL Radio_flag = TRUE;
391//wifi_setApBeaconRate(1, beaconRate);
392
developer1e5aa162022-09-13 16:06:24 +0800393BOOL multiple_set = FALSE;
394
developer06a01d92022-09-07 16:32:39 +0800395struct params
396{
397 char * name;
398 char * value;
399};
400
401static int _syscmd(char *cmd, char *retBuf, int retBufSize)
402{
403 FILE *f;
404 char *ptr = retBuf;
405 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
406
407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
408 if((f = popen(cmd, "r")) == NULL) {
409 fprintf(stderr,"\npopen %s error\n", cmd);
410 return RETURN_ERR;
411 }
412
413 while(!feof(f))
414 {
415 *ptr = 0;
416 if(bufSize>=128) {
417 bufbytes=128;
418 } else {
419 bufbytes=bufSize-1;
420 }
421
422 fgets(ptr,bufbytes,f);
423 readbytes=strlen(ptr);
424
425 if(!readbytes)
426 break;
427
428 bufSize-=readbytes;
429 ptr += readbytes;
430 }
431 cmd_ret = pclose(f);
432 retBuf[retBufSize-1]=0;
433 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
434
435 return cmd_ret >> 8;
436}
437
developerc707e972022-09-13 15:38:02 +0800438wifi_band wifi_index_to_band(int apIndex)
439{
440 char cmd[128] = {0};
441 char buf[64] = {0};
442 int freq = 0;
443 wifi_band band = band_invalid;
444
445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
446 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
447 _syscmd(cmd, buf, sizeof(buf));
448 freq = strtol(buf, NULL, 10);
449 if (freq > 2401 && freq < 2495)
450 band = band_2_4;
451 else if (freq > 5160 && freq < 5915)
452 band = band_5;
453 else if (freq > 5955 && freq < 7125)
454 band = band_6;
455
456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
457 return band;
458}
459
developer06a01d92022-09-07 16:32:39 +0800460static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
461{
462 char cmd[MAX_CMD_SIZE]={'\0'};
463 char buf[MAX_BUF_SIZE]={'\0'};
464 int ret = 0;
465
466 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
467 ret = _syscmd(cmd, buf, sizeof(buf));
468 if ((ret != 0) && (strlen(buf) == 0))
469 return -1;
470 snprintf(output, output_size, "%s", buf);
471
472 return 0;
473}
474
475static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
476{
477 char cmd[MAX_CMD_SIZE]={'\0'};
478 char buf[MAX_BUF_SIZE]={'\0'};
479
480 for(int i=0;i<item_count;i++)
481 {
482 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
483 if (strlen(buf) == 0) //Insert
484 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
485 else //Update
486 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
487 if(_syscmd(cmd, buf, sizeof(buf)))
488 return -1;
489 }
490
491 return 0;
492}
493
494static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
495{
developer1e5aa162022-09-13 16:06:24 +0800496 if (multiple_set == TRUE)
497 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800498 char cmd[MAX_CMD_SIZE]="", output[32]="";
499 FILE *fp;
500 int i;
501 //NOTE RELOAD should be done in ApplySSIDSettings
502
503 for(i=0; i<item_count; i++, list++)
504 {
505 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
506 if((fp = popen(cmd, "r"))==NULL)
507 {
508 perror("popen failed");
509 return -1;
510 }
511 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
512 {
513 pclose(fp);
514 perror("fgets failed");
515 return -1;
516 }
517 pclose(fp);
518 }
519 return 0;
520}
521
522static int wifi_reloadAp(int apIndex)
523{
developer1e5aa162022-09-13 16:06:24 +0800524 if (multiple_set == TRUE)
525 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800526 char cmd[MAX_CMD_SIZE]="";
527 char buf[MAX_BUF_SIZE]="";
528
529 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
530 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
531 return RETURN_ERR;
532
533 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
534 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
535 return RETURN_ERR;
536
537 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
538 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
539 return RETURN_ERR;
540
541 return RETURN_OK;
542}
543
544
545//For Getting Current Interface Name from corresponding hostapd configuration
546void GetInterfaceName(char *interface_name, char *conf_file)
547{
548 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
549 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
550 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
551}
552
553INT File_Reading(CHAR *file, char *Value)
554{
555 FILE *fp = NULL;
556 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
557 int count = 0;
558
559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
560 fp = popen(file,"r");
561 if(fp == NULL)
562 return RETURN_ERR;
563
564 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
565 {
566 for(count=0;buf[count]!='\n';count++)
567 copy_buf[count]=buf[count];
568 copy_buf[count]='\0';
569 }
570 strcpy(Value,copy_buf);
571 pclose(fp);
572 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
573
574 return RETURN_OK;
575}
576
577void wifi_RestartHostapd_2G()
578{
579 int Public2GApIndex = 4;
580
581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
582 wifi_setApEnable(Public2GApIndex, FALSE);
583 wifi_setApEnable(Public2GApIndex, TRUE);
584 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
585}
586
587void wifi_RestartHostapd_5G()
588{
589 int Public5GApIndex = 5;
590
591 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
592 wifi_setApEnable(Public5GApIndex, FALSE);
593 wifi_setApEnable(Public5GApIndex, TRUE);
594 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
595}
596
597void wifi_RestartPrivateWifi_2G()
598{
599 int PrivateApIndex = 0;
600
601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
602 wifi_setApEnable(PrivateApIndex, FALSE);
603 wifi_setApEnable(PrivateApIndex, TRUE);
604 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
605}
606
607void wifi_RestartPrivateWifi_5G()
608{
609 int Private5GApIndex = 1;
610
611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
612 wifi_setApEnable(Private5GApIndex, FALSE);
613 wifi_setApEnable(Private5GApIndex, TRUE);
614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
615}
616
617static int writeBandWidth(int radioIndex,char *bw_value)
618{
619 char buf[MAX_BUF_SIZE];
620 char cmd[MAX_CMD_SIZE];
621
622 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
623 if(_syscmd(cmd, buf, sizeof(buf)))
624 {
625 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
626 _syscmd(cmd, buf, sizeof(buf));
627 return RETURN_OK;
628 }
629
630 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
631 _syscmd(cmd,buf,sizeof(buf));
632 return RETURN_OK;
633}
634
635static int readBandWidth(int radioIndex,char *bw_value)
636{
637 char buf[MAX_BUF_SIZE];
638 char cmd[MAX_CMD_SIZE];
639 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
640 _syscmd(cmd,buf,sizeof(buf));
641 if(NULL!=strstr(buf,"20MHz"))
642 {
643 strcpy(bw_value,"20MHz");
644 }
645 else if(NULL!=strstr(buf,"40MHz"))
646 {
647 strcpy(bw_value,"40MHz");
648 }
649 else if(NULL!=strstr(buf,"80MHz"))
650 {
651 strcpy(bw_value,"80MHz");
652 }
653 else
654 {
655 return RETURN_ERR;
656 }
657 return RETURN_OK;
658}
659
developer39a5efb2022-09-13 16:09:06 +0800660INT wifi_getMaxRadioNumber(INT *max_radio_num)
661{
662 char cmd[64] = {0};
663 char buf[4] = {0};
664
665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
666
667 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
668 _syscmd(cmd, buf, sizeof(buf));
669 *max_radio_num = strtoul(buf, NULL, 10);
670
671 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
672
673 return RETURN_OK;
674}
675
developer5f222492022-09-13 15:21:52 +0800676// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800677INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
678{
developer5f222492022-09-13 15:21:52 +0800679 struct params params={'\0'};
680 char config_file[MAX_BUF_SIZE] = {0};
681 char buf[MAX_BUF_SIZE] = {'\0'};
682
683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
684 if (strlen (beaconRate) < 5)
685 return RETURN_ERR;
686 // Copy the numeric value
687 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
688 buf[strlen(beaconRate) - 4] = '\0';
689
690 params.name = "beacon_rate";
691 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
692 if (strncmp(buf, "5.5", 3) == 0) {
693 snprintf(buf, sizeof(buf), "55");
694 params.value = buf;
695 } else {
696 strcat(buf, "0");
697 params.value = buf;
698 }
699
700 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
701 wifi_hostapdWrite(config_file, &params, 1);
702 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
703 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
704
705 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800706}
707
708INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
709{
developer5f222492022-09-13 15:21:52 +0800710 char config_file[MAX_BUF_SIZE] = {'\0'};
711 char temp_output[MAX_BUF_SIZE] = {'\0'};
712 char buf[MAX_BUF_SIZE] = {'\0'};
713 float rate = 0;
714
715 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
716 if (NULL == beaconRate)
717 return RETURN_ERR;
718
719 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
720 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
721 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
722 if(strlen(buf) > 0) {
723 rate = atof(buf)/10;
724 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
725 } else {
726 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
727 }
728 strncpy(beaconRate, temp_output, sizeof(temp_output));
729 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
730
731 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800732}
733
734INT wifi_setLED(INT radioIndex, BOOL enable)
735{
736 return 0;
737}
738INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
739{
740 return RETURN_OK;
741}
742/**********************************************************************************
743 *
744 * Wifi Subsystem level function prototypes
745 *
746**********************************************************************************/
747//---------------------------------------------------------------------------------------------------
748//Wifi system api
749//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
750INT wifi_getHalVersion(CHAR *output_string) //RDKB
751{
752 if(!output_string)
753 return RETURN_ERR;
754 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
755
756 return RETURN_OK;
757}
758
759
760/* wifi_factoryReset() function */
761/**
762* @description Clears internal variables to implement a factory reset of the Wi-Fi
763* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
764*
765* @param None
766*
767* @return The status of the operation.
768* @retval RETURN_OK if successful.
769* @retval RETURN_ERR if any error is detected
770*
771* @execution Synchronous
772* @sideeffect None
773*
774* @note This function must not suspend and must not invoke any blocking system
775* calls. It should probably just send a message to a driver event handler task.
776*
777*/
778INT wifi_factoryReset()
779{
780 char cmd[128];
781
782 /*delete running hostapd conf files*/
783 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
784 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
785 system(cmd);
786 system("systemctl restart hostapd.service");
787
788 return RETURN_OK;
789}
790
791/* wifi_factoryResetRadios() function */
792/**
793* @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.
794*
795* @param None
796* @return The status of the operation
797* @retval RETURN_OK if successful
798* @retval RETURN_ERR if any error is detected
799*
800* @execution Synchronous
801*
802* @sideeffect None
803*
804* @note This function must not suspend and must not invoke any blocking system
805* calls. It should probably just send a message to a driver event handler task.
806*
807*/
808INT wifi_factoryResetRadios()
809{
810 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
811 return RETURN_OK;
812
813 return RETURN_ERR;
814}
815
816
817/* wifi_factoryResetRadio() function */
818/**
819* @description Restore selected radio parameters without touching access point parameters
820*
821* @param radioIndex - Index of Wi-Fi Radio channel
822*
823* @return The status of the operation.
824* @retval RETURN_OK if successful.
825* @retval RETURN_ERR if any error is detected
826*
827* @execution Synchronous.
828* @sideeffect None.
829*
830* @note This function must not suspend and must not invoke any blocking system
831* calls. It should probably just send a message to a driver event handler task.
832*
833*/
834INT wifi_factoryResetRadio(int radioIndex) //RDKB
835{
developer5ff7f5f2022-09-13 15:12:16 +0800836 system("systemctl stop hostapd.service");
837
developer06a01d92022-09-07 16:32:39 +0800838 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
839 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800840 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800841 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800842 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800843 else
844 return RETURN_ERR;
845
developer5ff7f5f2022-09-13 15:12:16 +0800846 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800847 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
848 return RETURN_OK;
849}
850
851/* wifi_initRadio() function */
852/**
853* Description: This function call initializes the specified radio.
854* Implementation specifics may dictate the functionality since
855* different hardware implementations may have different initilization requirements.
856* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
857*
858* @return The status of the operation.
859* @retval RETURN_OK if successful.
860* @retval RETURN_ERR if any error is detected
861*
862* @execution Synchronous.
863* @sideeffect None.
864*
865* @note This function must not suspend and must not invoke any blocking system
866* calls. It should probably just send a message to a driver event handler task.
867*
868*/
869INT wifi_initRadio(INT radioIndex)
870{
871 //TODO: Initializes the wifi subsystem (for specified radio)
872 return RETURN_OK;
873}
874void macfilter_init()
875{
876 char count[4]={'\0'};
877 char buf[253]={'\0'};
878 char tmp[19]={'\0'};
879 int dev_count,block,mac_entry=0;
880 char res[4]={'\0'};
881 char acl_file_path[64] = {'\0'};
882 FILE *fp = NULL;
883 int index=0;
884 char iface[10]={'\0'};
885 char config_file[MAX_BUF_SIZE] = {0};
886
887
888 sprintf(acl_file_path,"/tmp/mac_filter.sh");
889
890 fp=fopen(acl_file_path,"w+");
891 sprintf(buf,"#!/bin/sh \n");
892 fprintf(fp,"%s\n",buf);
893
894 system("chmod 0777 /tmp/mac_filter.sh");
895
896 for(index=0;index<=1;index++)
897 {
898 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
899 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
900 sprintf(buf,"syscfg get %dcountfilter",index);
901 _syscmd(buf,count,sizeof(count));
902 mac_entry=atoi(count);
903
904 sprintf(buf,"syscfg get %dblockall",index);
905 _syscmd(buf,res,sizeof(res));
906 block = atoi(res);
907
908 //Allow only those macs mentioned in ACL
909 if(block==1)
910 {
911 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
912 fprintf(fp,"%s\n",buf);
913 for(dev_count=1;dev_count<=mac_entry;dev_count++)
914 {
915 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
916 _syscmd(buf,tmp,sizeof(tmp));
917 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
918 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
919 fprintf(fp,"%s\n",buf);
920 }
921 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
922 fprintf(fp,"%s\n",buf);
923 }
924
925 //Block all the macs mentioned in ACL
926 else if(block==2)
927 {
928 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
929 fprintf(fp,"%s\n",buf);
930
931 for(dev_count=1;dev_count<=mac_entry;dev_count++)
932 {
933 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
934 _syscmd(buf,tmp,sizeof(tmp));
935 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
936 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
937 fprintf(fp,"%s\n",buf);
938 }
939 }
940 }
941 fclose(fp);
942}
943
944// Initializes the wifi subsystem (all radios)
945INT wifi_init() //RDKB
946{
947 char interface[MAX_BUF_SIZE]={'\0'};
948 char bridge_name[MAX_BUF_SIZE]={'\0'};
949 INT len=0;
950
951 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
952 //Not intitializing macfilter for Turris-Omnia Platform for now
953 //macfilter_init();
954
955 system("/usr/sbin/iw reg set US");
956 system("systemctl start hostapd.service");
957 sleep(2);//sleep to wait for hostapd to start
958
959 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
960
961 return RETURN_OK;
962}
963
964/* wifi_reset() function */
965/**
966* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
967* Implementation specifics may dictate what is actualy reset since
968* different hardware implementations may have different requirements.
969* Parameters : None
970*
971* @return The status of the operation.
972* @retval RETURN_OK if successful.
973* @retval RETURN_ERR if any error is detected
974*
975* @execution Synchronous.
976* @sideeffect None.
977*
978* @note This function must not suspend and must not invoke any blocking system
979* calls. It should probably just send a message to a driver event handler task.
980*
981*/
982INT wifi_reset()
983{
984 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +0800985 system("systemctl stop hostapd.service");
986 sleep(2);
987 system("systemctl start hostapd.service");
988 sleep(5);
developer06a01d92022-09-07 16:32:39 +0800989 return RETURN_OK;
990}
991
992/* wifi_down() function */
993/**
994* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
995* Implementation specifics may dictate some functionality since
996* different hardware implementations may have different requirements.
997*
998* @param None
999*
1000* @return The status of the operation
1001* @retval RETURN_OK if successful
1002* @retval RETURN_ERR if any error is detected
1003*
1004* @execution Synchronous
1005* @sideeffect None
1006*
1007* @note This function must not suspend and must not invoke any blocking system
1008* calls. It should probably just send a message to a driver event handler task.
1009*
1010*/
1011INT wifi_down()
1012{
1013 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001014 system("systemctl stop hostapd.service");
1015 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001016 return RETURN_OK;
1017}
1018
1019
1020/* wifi_createInitialConfigFiles() function */
1021/**
1022* @description This function creates wifi configuration files. The format
1023* and content of these files are implementation dependent. This function call is
1024* used to trigger this task if necessary. Some implementations may not need this
1025* function. If an implementation does not need to create config files the function call can
1026* do nothing and return RETURN_OK.
1027*
1028* @param None
1029*
1030* @return The status of the operation
1031* @retval RETURN_OK if successful
1032* @retval RETURN_ERR if any error is detected
1033*
1034* @execution Synchronous
1035* @sideeffect None
1036*
1037* @note This function must not suspend and must not invoke any blocking system
1038* calls. It should probably just send a message to a driver event handler task.
1039*
1040*/
1041INT wifi_createInitialConfigFiles()
1042{
1043 //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)
1044 return RETURN_OK;
1045}
1046
1047// outputs the country code to a max 64 character string
1048INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1049{
developer7543b3b2022-09-13 13:47:17 +08001050 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1051 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001052 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001053
1054 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1055 _syscmd(cmd, buf, sizeof(buf));
1056 if(strlen(buf) > 0)
1057 snprintf(output_string, 64, "%s", buf);
1058 else
1059 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001060
1061 return RETURN_OK;
1062}
1063
1064INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1065{
1066 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001067 char str[MAX_BUF_SIZE]={'\0'};
1068 char cmd[MAX_CMD_SIZE]={'\0'};
1069 struct params params;
1070 char config_file[MAX_BUF_SIZE] = {0};
1071
1072 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1073 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1074 return RETURN_ERR;
1075
1076 params.name = "country_code";
1077 params.value = CountryCode;
1078 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1079 int ret = wifi_hostapdWrite(config_file, &params, 1);
1080 if (ret) {
1081 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1082 ,__func__, ret);
1083 }
1084
1085 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1086 if (ret) {
1087 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1088 ,__func__, ret);
1089 }
1090 wifi_reloadAp(radioIndex);
1091 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1092
developer06a01d92022-09-07 16:32:39 +08001093 return RETURN_OK;
1094}
1095
developera748dcf2022-09-13 15:56:48 +08001096INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1097{
1098 char channel_util_file[64] = {0};
1099 char cmd[128] = {0};
1100 char buf[128] = {0};
1101 char line[128] = {0};
1102 char *param = NULL, *value = NULL;
1103 int read = 0;
1104 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1105 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1106 size_t len = 0;
1107 FILE *f = NULL;
1108
1109 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1110
1111 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1112 _syscmd(cmd, buf, sizeof(buf));
1113 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1114
1115 memset(cmd, 0, sizeof(cmd));
1116 memset(buf, 0, sizeof(buf));
1117 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1118 if ((f = popen(cmd, "r")) == NULL) {
1119 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1120 return RETURN_ERR;
1121 }
1122
1123 read = getline(&line, &len, f);
1124 while (read != -1) {
1125 param = strtok(line, ":\t");
1126 value = strtok(NULL, " ");
1127 if(strstr(param, "frequency") != NULL) {
1128 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1129 }
1130 if(strstr(param, "noise") != NULL) {
1131 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1132 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1133 }
1134 if(strstr(param, "channel active time") != NULL) {
1135 ActiveTime = strtol(value, NULL, 10);
1136 }
1137 if(strstr(param, "channel busy time") != NULL) {
1138 BusyTime = strtol(value, NULL, 10);
1139 }
1140 if(strstr(param, "channel transmit time") != NULL) {
1141 TransmitTime = strtol(value, NULL, 10);
1142 }
1143 read = getline(&line, &len, f);
1144 }
1145 pclose(f);
1146
1147 // The file should store the last active, busy and transmit time
1148 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1149 f = fopen(channel_util_file, "r");
1150 if (f != NULL) {
1151 read = getline(&line, &len, f);
1152 preActiveTime = strtol(line, NULL, 10);
1153 read = getline(&line, &len, f);
1154 preBusyTime = strtol(line, NULL, 10);
1155 read = getline(&line, &len, f);
1156 preTransmitTime = strtol(line, NULL, 10);
1157 fclose(f);
1158 }
1159
1160 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1161 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1162
1163 f = fopen(channel_util_file, "w");
1164 if (f != NULL) {
1165 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1166 fclose(f);
1167 }
1168 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1169 return RETURN_OK;
1170}
1171
developer06a01d92022-09-07 16:32:39 +08001172/**********************************************************************************
1173 *
1174 * Wifi radio level function prototypes
1175 *
1176**********************************************************************************/
1177
1178//Get the total number of radios in this wifi subsystem
1179INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1180{
1181 if (NULL == output)
1182 return RETURN_ERR;
1183 *output = 2;
1184
1185 return RETURN_OK;
1186}
1187
1188//Get the total number of SSID entries in this wifi subsystem
1189INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1190{
1191 if (NULL == output)
1192 return RETURN_ERR;
1193 *output = MAX_APS;
1194
1195 return RETURN_OK;
1196}
1197
1198//Get the Radio enable config parameter
1199INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1200{
1201 char interface_path[MAX_CMD_SIZE] = {0};
1202 FILE *fp = NULL;
1203
1204 if (NULL == output_bool)
1205 return RETURN_ERR;
1206
1207 *output_bool = FALSE;
1208 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1209 return RETURN_ERR;
1210
1211 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1212 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001213 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001214 {
developercf48e482022-09-13 14:49:50 +08001215 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001216 }
1217 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001218 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1219 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1220 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001221
developercf48e482022-09-13 14:49:50 +08001222 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1223 *output_bool = TRUE;
1224 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001225 return RETURN_OK;
1226}
1227
1228INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1229{
1230 char cmd[MAX_CMD_SIZE] = {0};
1231 char buf[MAX_CMD_SIZE] = {0};
1232 int apIndex, ret;
1233 FILE *fp = NULL;
1234
1235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1236 if(enable==FALSE)
1237 {
1238 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1239 {
1240 //Detaching %s%d from hostapd daemon
1241 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1242 _syscmd(cmd, buf, sizeof(buf));
1243 if(strncmp(buf, "OK", 2))
1244 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1245 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1246 _syscmd(cmd, buf, sizeof(buf));
1247 }
developer456aa3e2022-09-13 14:27:36 +08001248 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001249 _syscmd(cmd, buf, sizeof(buf));
1250 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001251 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001252 }
1253 else
1254 {
developer456aa3e2022-09-13 14:27:36 +08001255 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001256 _syscmd(cmd, buf, sizeof(buf));
1257 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001258 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001259 sleep(1);
1260 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1261 {
1262 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1263 fp = fopen(cmd, "r");
1264 if(!fp)
1265 {
1266 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1267 _syscmd(cmd, buf, sizeof(buf));
1268 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1269 _syscmd(cmd, buf, sizeof(buf));
1270 }
1271 if(fp)
1272 fclose(fp);
1273 }
1274 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1275 {
1276 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1277 ret = _syscmd(cmd, buf, sizeof(buf));
1278 if ( ret == RETURN_ERR)
1279 {
1280 fprintf(stderr, "VAP interface creation failed\n");
1281 continue;
1282 }
1283 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1284 _syscmd(cmd, buf, sizeof(buf));
1285 if(*buf == '1')
1286 {
1287 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1288 radioIndex, apIndex);
1289 _syscmd(cmd, buf, sizeof(buf));
1290 if(strncmp(buf, "OK", 2))
1291 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1292 }
1293 }
1294 }
1295
1296 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1297 return RETURN_OK;
1298}
1299
1300//Get the Radio enable status
1301INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1302{
1303 if (NULL == output_bool)
1304 return RETURN_ERR;
1305
1306 return wifi_getRadioEnable(radioIndex, output_bool);
1307}
1308
1309//Get the Radio Interface name from platform, eg "wlan0"
1310INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1311{
1312 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1313 return RETURN_ERR;
1314 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1315
1316 return RETURN_OK;
1317}
1318
1319//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1320//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.
1321INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1322{
1323 char cmd[1024] = {0};
1324 char buf[1024] = {0};
1325 char HConf_file[MAX_BUF_SIZE] = {'\0'};
1326 char interface_name[50] = {0};
1327
1328 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1329 if (NULL == output_string)
1330 return RETURN_ERR;
1331
1332 sprintf(HConf_file,"%s%d%s","/nvram/hostapd",radioIndex,".conf");
1333 GetInterfaceName(interface_name,HConf_file);
1334
1335 sprintf(cmd, "iwconfig %s | grep 'Bit Rate' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1,2", interface_name);
1336 _syscmd(cmd, buf, sizeof(buf));
1337
1338 if(strlen(buf) > 0)
1339 snprintf(output_string, 64, "%s", buf);
1340 else
1341 {
1342 wifi_getRadioOperatingChannelBandwidth(radioIndex,buf);
1343 if((strcmp(buf,"20MHz") == 0) && (radioIndex == 0))
1344 strcpy(output_string,"144 Mb/s");
1345 else if((strcmp(buf,"20MHz") == 0) && (radioIndex == 1))
1346 strcpy(output_string,"54 Mb/s");
1347 else if((strcmp(buf,"40MHz") == 0) && (radioIndex == 1))
1348 strcpy(output_string,"300 Mb/s");
1349 //TODO: CHECK VALID VALUE
1350 }
1351 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1352
1353 return RETURN_OK;
1354}
1355#if 0
1356INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1357{
1358 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1359 char cmd[64];
1360 char buf[1024];
1361 int apIndex;
1362
1363 if (NULL == output_string)
1364 return RETURN_ERR;
1365
1366 apIndex=(radioIndex==0)?0:1;
1367
1368 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1369 _syscmd(cmd,buf, sizeof(buf));
1370
1371 snprintf(output_string, 64, "%s", buf);
1372 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1373 return RETURN_OK;
1374}
1375#endif
1376
1377
1378//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1379//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.
1380INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1381{
developer963da0c2022-09-13 15:58:27 +08001382 wifi_band band = band_invalid;
1383
developer06a01d92022-09-07 16:32:39 +08001384 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1385 if (NULL == output_string)
1386 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001387
1388 band = wifi_index_to_band(radioIndex);
1389
1390 memset(output_string, 0, 10);
1391 if (band == band_2_4)
1392 strcpy(output_string, "2.4GHz");
1393 else if (band == band_5)
1394 strcpy(output_string, "5GHz");
1395 else if (band == band_6)
1396 strcpy(output_string, "6GHz");
1397 else
1398 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001399 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1400
1401 return RETURN_OK;
1402#if 0
1403 char buf[MAX_BUF_SIZE]={'\0'};
1404 char str[MAX_BUF_SIZE]={'\0'};
1405 char cmd[MAX_CMD_SIZE]={'\0'};
1406 char *ch=NULL;
1407 char *ch2=NULL;
1408
1409 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1410 if (NULL == output_string)
1411 return RETURN_ERR;
1412
1413
1414 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1415
1416 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1417 {
1418 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1419 return RETURN_ERR;
1420 }
1421 ch=strchr(buf,'\n');
1422 *ch='\0';
1423 ch=strchr(buf,'=');
1424 if(ch==NULL)
1425 return RETURN_ERR;
1426
1427
1428 ch++;
1429
1430 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1431 strcpy(buf,"0");
1432 if(strlen(ch) == 1)
1433 ch=strcat(buf,ch);
1434
1435
1436 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1437
1438 if(_syscmd(cmd,str,64) == RETURN_ERR)
1439 {
1440 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1441 return RETURN_ERR;
1442 }
1443
1444
1445 ch2=strchr(str,'\n');
1446 //replace \n with \0
1447 *ch2='\0';
1448 ch2=strchr(str,'=');
1449 if(ch2==NULL)
1450 {
1451 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1452 return RETURN_ERR;
1453 }
1454 else
1455 wifi_dbg_printf("%s",ch2+1);
1456
1457
1458 ch2++;
1459
1460
1461 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1462
1463 memset(buf,'\0',sizeof(buf));
1464 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1465 {
1466 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1467 return RETURN_ERR;
1468 }
1469 if (strstr(buf,"2.4") != NULL )
1470 strcpy(output_string,"2.4GHz");
1471 else if(strstr(buf,"5.") != NULL )
1472 strcpy(output_string,"5GHz");
1473 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1474
1475 return RETURN_OK;
1476#endif
1477}
1478
1479//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1480//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.
1481INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1482{
1483 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1484 if (NULL == output_string)
1485 return RETURN_ERR;
1486 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1487 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1488
1489 return RETURN_OK;
1490#if 0
1491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1492 char buf[MAX_BUF_SIZE]={'\0'};
1493 char str[MAX_BUF_SIZE]={'\0'};
1494 char cmd[MAX_CMD_SIZE]={'\0'};
1495 char *ch=NULL;
1496 char *ch2=NULL;
1497 char ch1[5]="0";
1498
1499 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1500
1501 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1502 {
1503 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1504 return RETURN_ERR;
1505 }
1506
1507 ch=strchr(buf,'\n');
1508 *ch='\0';
1509 ch=strchr(buf,'=');
1510 if(ch==NULL)
1511 return RETURN_ERR;
1512 ch++;
1513
1514 if(strlen(ch)==1)
1515 {
1516 strcat(ch1,ch);
1517
1518 }
1519 else
1520 {
1521 strcpy(ch1,ch);
1522 }
1523
1524
1525
1526 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1527 if(_syscmd(cmd,str,64) == RETURN_ERR)
1528 {
1529 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1530 return RETURN_ERR;
1531 }
1532
1533
1534 ch2=strchr(str,'\n');
1535 //replace \n with \0
1536 *ch2='\0';
1537 ch2=strchr(str,'=');
1538 if(ch2==NULL)
1539 {
1540 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1541 return RETURN_ERR;
1542 }
1543 else
1544 wifi_dbg_printf("%s",ch2+1);
1545 ch2++;
1546
1547
1548 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1549 memset(buf,'\0',sizeof(buf));
1550 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1551 {
1552 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1553 return RETURN_ERR;
1554 }
1555
1556
1557 if(strstr(buf,"2.4")!=NULL)
1558 {
1559 strcpy(output_string,"2.4GHz");
1560 }
1561 if(strstr(buf,"5.")!=NULL)
1562 {
1563 strcpy(output_string,"5GHz");
1564 }
1565 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1566 return RETURN_OK;
1567#endif
1568}
1569
1570//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1571//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.
1572INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1573{
developer963da0c2022-09-13 15:58:27 +08001574 char cmd[128]={0};
1575 char buf[128]={0};
1576 char temp_output[128] = {0};
1577 wifi_band band;
1578
1579 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001580 if (NULL == output_string)
1581 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001582
1583 band = wifi_index_to_band(radioIndex);
1584 if (band == band_2_4) {
1585 strcat(temp_output, "b,g,");
1586 } else if (band == band_5) {
1587 strcat(temp_output, "a,");
1588 }
1589
1590 // ht capabilities
1591 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);
1592 _syscmd(cmd, buf, sizeof(buf));
1593 if (strncmp(buf, "0x00", 4) != 0) {
1594 strcat(temp_output, "n,");
1595 }
developer06a01d92022-09-07 16:32:39 +08001596
developer963da0c2022-09-13 15:58:27 +08001597 // vht capabilities
1598 if (band == band_5) {
1599 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1600 _syscmd(cmd, buf, sizeof(buf));
1601 if (strncmp(buf, "0x00000000", 10) != 0) {
1602 strcat(temp_output, "ac,");
1603 }
1604 }
1605
1606 // he capabilities
1607 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);
1608 _syscmd(cmd, buf, sizeof(buf));
1609 if (strncmp (buf, "0x0000", 6) != 0) {
1610 strcat(temp_output, "ax,");
1611 }
1612
1613 // Remove the last comma
1614 if (strlen(temp_output) != 0)
1615 temp_output[strlen(temp_output)-1] = '\0';
1616 strncpy(output_string, temp_output, strlen(temp_output));
1617 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001618 return RETURN_OK;
1619}
1620
1621//Get the radio operating mode, and pure mode flag. eg: "ac"
1622//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.
1623INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1624{
1625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1626 if (NULL == output_string)
1627 return RETURN_ERR;
1628
1629 if (radioIndex == 0) {
1630 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1631 *gOnly = FALSE;
1632 *nOnly = TRUE;
1633 *acOnly = FALSE;
1634 } else {
1635 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1636 *gOnly = FALSE;
1637 *nOnly = FALSE;
1638 *acOnly = FALSE;
1639 }
1640 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1641
1642 return RETURN_OK;
1643#if 0
1644 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1645 char buf[64] = {0};
1646 char config_file[MAX_BUF_SIZE] = {0};
1647
1648 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1649 return RETURN_ERR;
1650
1651 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1652 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1653
1654 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1655 if (strlen(buf) == 0)
1656 {
1657 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1658 return RETURN_ERR;
1659 }
1660 if(strcmp(buf,"g")==0)
1661 {
1662 wifi_dbg_printf("\nG\n");
1663 *gOnly=TRUE;
1664 *nOnly=FALSE;
1665 *acOnly=FALSE;
1666 }
1667 else if(strcmp(buf,"n")==0)
1668 {
1669 wifi_dbg_printf("\nN\n");
1670 *gOnly=FALSE;
1671 *nOnly=TRUE;
1672 *acOnly=FALSE;
1673 }
1674 else if(strcmp(buf,"ac")==0)
1675 {
1676 wifi_dbg_printf("\nac\n");
1677 *gOnly=FALSE;
1678 *nOnly=FALSE;
1679 *acOnly=TRUE;
1680 }
1681 /* hostapd-5G.conf has "a" as hw_mode */
1682 else if(strcmp(buf,"a")==0)
1683 {
1684 wifi_dbg_printf("\na\n");
1685 *gOnly=FALSE;
1686 *nOnly=FALSE;
1687 *acOnly=FALSE;
1688 }
1689 else
1690 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1691
1692 //for a,n mode
1693 if(radioIndex == 1)
1694 {
1695 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1696 if(strcmp(buf,"1")==0)
1697 {
1698 strncpy(output_string, "n", 1);
1699 *nOnly=FALSE;
1700 }
1701 }
1702
1703 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1705 return RETURN_OK;
1706#endif
1707}
1708
developerdb744382022-09-13 15:34:54 +08001709INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1710{
1711 char cmd[128] = {0};
1712 char buf[64] = {0};
1713 char config_file[64] = {0};
1714 wifi_band band;
1715
1716 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1717 if(NULL == output_string || NULL == pureMode)
1718 return RETURN_ERR;
1719
1720 // grep all of the ieee80211 protocol config set to 1
1721 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1722 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1723 _syscmd(cmd, buf, sizeof(buf));
1724
1725 band = wifi_index_to_band(radioIndex);
1726 // puremode is a bit map
1727 *pureMode = 0;
1728 if (band == band_2_4) {
1729 strcat(output_string, "b,g");
1730 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1731 if (strstr(buf, "n") != NULL) {
1732 strcat(output_string, ",n");
1733 *pureMode |= WIFI_MODE_N;
1734 }
1735 if (strstr(buf, "ax") != NULL) {
1736 strcat(output_string, ",ax");
1737 *pureMode |= WIFI_MODE_AX;
1738 }
1739 } else if (band == band_5) {
1740 strcat(output_string, "a");
1741 *pureMode |= WIFI_MODE_A;
1742 if (strstr(buf, "n") != NULL) {
1743 strcat(output_string, ",n");
1744 *pureMode |= WIFI_MODE_N;
1745 }
1746 if (strstr(buf, "ac") != NULL) {
1747 strcat(output_string, ",ac");
1748 *pureMode |= WIFI_MODE_AC;
1749 }
1750 if (strstr(buf, "ax") != NULL) {
1751 strcat(output_string, ",ax");
1752 *pureMode |= WIFI_MODE_AX;
1753 }
1754 } else if (band == band_6) {
1755 if (strstr(buf, "ax") != NULL) {
1756 strcat(output_string, "ax");
1757 *pureMode |= WIFI_MODE_AX;
1758 }
1759 }
1760
1761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1762 return RETURN_OK;
1763}
1764
1765// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001766INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1767{
1768 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1769 if (strcmp (channelMode,"11A") == 0)
1770 {
1771 writeBandWidth(radioIndex,"20MHz");
1772 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1773 printf("\nChannel Mode is 802.11a (5GHz)\n");
1774 }
1775 else if (strcmp (channelMode,"11NAHT20") == 0)
1776 {
1777 writeBandWidth(radioIndex,"20MHz");
1778 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1779 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1780 }
1781 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1782 {
1783 writeBandWidth(radioIndex,"40MHz");
1784 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1785 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1786 }
1787 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1788 {
1789 writeBandWidth(radioIndex,"40MHz");
1790 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1791 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1792 }
1793 else if (strcmp (channelMode,"11ACVHT20") == 0)
1794 {
1795 writeBandWidth(radioIndex,"20MHz");
1796 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1797 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1798 }
1799 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1800 {
1801 writeBandWidth(radioIndex,"40MHz");
1802 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1803 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1804 }
1805 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1806 {
1807 writeBandWidth(radioIndex,"40MHz");
1808 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1809 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1810 }
1811 else if (strcmp (channelMode,"11ACVHT80") == 0)
1812 {
1813 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1814 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1815 }
1816 else if (strcmp (channelMode,"11ACVHT160") == 0)
1817 {
1818 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1819 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1820 }
1821 else if (strcmp (channelMode,"11B") == 0)
1822 {
1823 writeBandWidth(radioIndex,"20MHz");
1824 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1825 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1826 }
1827 else if (strcmp (channelMode,"11G") == 0)
1828 {
1829 writeBandWidth(radioIndex,"20MHz");
1830 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1831 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1832 }
1833 else if (strcmp (channelMode,"11NGHT20") == 0)
1834 {
1835 writeBandWidth(radioIndex,"20MHz");
1836 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1837 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1838 }
1839 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1840 {
1841 writeBandWidth(radioIndex,"40MHz");
1842 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1843 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1844 }
1845 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1846 {
1847 writeBandWidth(radioIndex,"40MHz");
1848 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1849 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1850 }
1851 else
1852 {
1853 return RETURN_ERR;
1854 }
1855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1856
1857 return RETURN_OK;
1858}
1859
developerdb744382022-09-13 15:34:54 +08001860// Set the radio operating mode, and pure mode flag.
1861INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1862{
1863 int num_hostapd_support_mode = 3; // n, ac, ax
1864 struct params list[num_hostapd_support_mode];
1865 char config_file[64] = {0};
1866 char bandwidth[16] = {0};
1867 int mode_check_bit = 1 << 3; // n mode
1868 wifi_ieee80211_Mode mode = (wifi_ieee80211_Mode)pureMode;
1869
1870 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1871 // Set radio mode
1872 list[0].name = "ieee80211n";
1873 list[1].name = "ieee80211ac";
1874 list[2].name = "ieee80211ax";
1875 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1876
1877 // check the bit map from n to ax, and set hostapd config
1878 if (mode & WIFI_MODE_N)
1879 list[0].value = "1";
1880 else
1881 list[0].value = "0";
1882 if (mode & WIFI_MODE_AC)
1883 list[1].value = "1";
1884 else
1885 list[1].value = "0";
1886 if (mode & WIFI_MODE_AX)
1887 list[2].value = "1";
1888 else
1889 list[2].value = "0";
1890 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1891
1892 if (channelMode == NULL || strlen(channelMode) == 0)
1893 return RETURN_OK;
1894 // Set bandwidth
1895 if (strstr(channelMode, "40") != NULL)
1896 strcpy(bandwidth, "40MHz");
1897 else if (strstr(channelMode, "80") != NULL)
1898 strcpy(bandwidth, "80MHz");
1899 else if (strstr(channelMode, "160") != NULL)
1900 strcpy(bandwidth, "160MHz");
1901 else // 11A, 11B, 11G....
1902 strcpy(bandwidth, "20MHz");
1903
1904 writeBandWidth(radioIndex, bandwidth);
1905 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
1906
1907 wifi_reloadAp(radioIndex);
1908 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1909
1910 return RETURN_OK;
1911}
1912
developer06a01d92022-09-07 16:32:39 +08001913//Get the list of supported channel. eg: "1-11"
1914//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.
1915INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
1916{
developer6318ed52022-09-13 15:17:58 +08001917 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001918 if (NULL == output_string)
1919 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08001920 char cmd[256] = {0};
1921 char buf[128] = {0};
1922 BOOL dfs_enable = false;
1923 // Parse possible channel number and separate them with commas.
1924 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
1925 if (dfs_enable)
1926 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
1927 else
1928 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);
1929
1930 _syscmd(cmd,buf,sizeof(buf));
1931 strncpy(output_string, buf, sizeof(buf));
1932
1933 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1934 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08001935#if 0
1936 char IFName[50] ={0};
1937 char buf[MAX_BUF_SIZE] = {0};
1938 char cmd[MAX_CMD_SIZE] = {0};
1939 int count = 0;
1940 if (NULL == output_string)
1941 return RETURN_ERR;
1942
1943 //snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
1944 if(radioIndex == 0)
1945 {
1946 GetInterfaceName(IFName,"/nvram/hostapd0.conf");
1947 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'");
1948 }
1949 else if(radioIndex == 1)
1950 {
1951 GetInterfaceName(IFName,"/nvram/hostapd1.conf");
1952 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'");
1953 }
1954 _syscmd(cmd, buf, sizeof(buf));
1955 if(strlen(buf) > 0)
1956 strcpy(output_string,buf);
1957 else
1958 strcpy(output_string,"0");
1959#endif
1960 return RETURN_OK;
1961}
1962
1963//Get the list for used channel. eg: "1,6,9,11"
1964//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.
1965INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
1966{
1967 if (NULL == output_string)
1968 return RETURN_ERR;
1969 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
1970#if 0
1971 char IFName[50] ={0};
1972 char buf[MAX_BUF_SIZE] = {0};
1973 char cmd[MAX_CMD_SIZE] = {0};
1974 if (NULL == output_string)
1975 return RETURN_ERR;
1976
1977 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
1978 if(radioIndex == 0)
1979 {
1980 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
1981 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'");
1982 }
1983 else if(radioIndex == 1)
1984 {
1985 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
1986 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'");
1987 }
1988 _syscmd(cmd,buf, sizeof(buf));
1989 if(strlen(buf) > 0)
1990 strcpy(output_string,buf);
1991 else
1992 strcpy(output_string,"0");
1993#endif
1994 return RETURN_OK;
1995}
1996
1997//Get the running channel number
1998INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
1999{
developerda1ed692022-09-13 13:59:20 +08002000#ifdef MTK_IMPL
2001 if(!wifi_getApChannel(radioIndex, output_ulong))
2002 return RETURN_OK;
2003 else
2004 return RETURN_ERR;
2005#else
developer06a01d92022-09-07 16:32:39 +08002006 char cmd[1024] = {0}, buf[5] = {0};
2007
2008 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2009 if (NULL == output_ulong)
2010 return RETURN_ERR;
2011
2012 snprintf(cmd, sizeof(cmd),
2013 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2014 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2015 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2016 _syscmd(cmd, buf, sizeof(buf));
2017
2018 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2019 if (*output_ulong <= 0) {
2020 *output_ulong = 0;
2021 return RETURN_ERR;
2022 }
2023
2024 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2025 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002026#endif
developer06a01d92022-09-07 16:32:39 +08002027}
2028
2029
2030INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2031{
2032 char cmd[1024] = {0}, buf[5] = {0};
2033 char interface_name[50] = {0};
2034
2035 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2036 if (NULL == output_ulong)
2037 return RETURN_ERR;
2038
2039 wifi_getApName(apIndex,interface_name);
2040 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2041 _syscmd(cmd,buf,sizeof(buf));
2042 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2043 if (*output_ulong == 0) {
2044 return RETURN_ERR;
2045 }
2046
2047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2048 return RETURN_OK;
2049}
2050
2051//Storing the previous channel value
2052INT wifi_storeprevchanval(INT radioIndex)
2053{
2054 char buf[256] = {0};
2055 char output[4]={'\0'};
2056 char config_file[MAX_BUF_SIZE] = {0};
2057 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2058 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2059 if(radioIndex == 0)
2060 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2061 else if(radioIndex == 1)
2062 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2063 system(buf);
2064 Radio_flag = FALSE;
2065 return RETURN_OK;
2066}
2067
2068//Set the running channel number
2069INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2070{
2071 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2072 struct params params={'\0'};
2073 char str_channel[4]={'\0'};
2074 struct params list;
2075 char config_file[MAX_BUF_SIZE] = {0};
2076
2077 list.name = "channel";
2078
2079 if(Radio_flag == TRUE)
2080 wifi_storeprevchanval(radioIndex); //for autochannel
2081
2082 if(radioIndex == 0)
2083 {
2084 switch(channel)
2085 {
2086 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
2087 sprintf(str_channel,"%ld", channel);
2088 list.value = str_channel;
2089 break;
2090 default:
2091 return RETURN_ERR;
2092 }
2093 }
2094 else if(radioIndex == 1)
2095 {
2096 switch(channel)
2097 {
2098 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:
2099 sprintf(str_channel,"%ld", channel);
2100 list.value = str_channel;
2101 break;
2102 default:
2103 return RETURN_ERR;
2104 }
2105 }
2106
2107 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS;i++)
2108 {
2109 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2110 wifi_hostapdWrite(config_file,&list,1);
2111 }
2112
2113 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2114 return RETURN_OK;
2115 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2116 }
2117
2118INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2119{
2120 struct params list;
2121 char str_idx[16];
2122 char config_file[MAX_BUF_SIZE];
2123
2124 list.name = "vht_oper_centr_freq_seg0_idx";
2125 snprintf(str_idx, sizeof(str_idx), "%d", channel);
2126 list.value = str_idx;
2127
2128 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2129 {
2130 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2131 wifi_hostapdWrite(config_file, &list, 1);
2132 }
2133
2134 return RETURN_OK;
2135}
2136
2137//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2138//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2139INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2140{
2141 //Set to wifi config only. Wait for wifi reset to apply.
2142 char buf[256] = {0};
2143 char str_channel[256] = {0};
2144 int count = 0;
2145 ULONG Value = 0;
2146 FILE *fp = NULL;
2147 if(enable == TRUE)
2148 {
2149 if(radioIndex == 0)
2150 {
2151 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
2152 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
2153 }
2154 else if(radioIndex == 1)
2155 {
2156 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
2157 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
2158 }
2159 if(fp == NULL) //first time boot-up
2160 {
2161 if(radioIndex == 0)
2162 Value = 6;
2163 else if(radioIndex == 1)
2164 Value = 36;
2165 }
2166 else
2167 {
2168 if(fgets(buf,sizeof(buf),fp) != NULL)
2169 {
2170 for(count = 0;buf[count]!='\n';count++)
2171 str_channel[count] = buf[count];
2172 str_channel[count] = '\0';
2173 Value = atol(str_channel);
2174 printf("%sValue is %ld \n",__FUNCTION__,Value);
2175 pclose(fp);
2176 }
2177 }
2178 Radio_flag = FALSE;//for storing previous channel value
2179 wifi_setRadioChannel(radioIndex,Value);
2180 return RETURN_OK;
2181 }
2182 return RETURN_ERR;
2183}
2184
2185INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2186{
2187 if (NULL == output_bool)
2188 return RETURN_ERR;
2189 *output_bool=FALSE;
2190 return RETURN_OK;
2191}
2192
2193INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2194{
2195 if (NULL == output_bool)
2196 return RETURN_ERR;
2197 *output_bool=FALSE;
2198 return RETURN_OK;
2199}
2200
2201INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2202{
2203 //Set to wifi config only. Wait for wifi reset to apply.
2204 return RETURN_OK;
2205}
2206
2207INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2208{
2209 return RETURN_OK;
2210}
2211
2212INT wifi_factoryResetAP(int apIndex)
2213{
2214 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2215 //factory reset is not done for now on Turris
2216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2217 return RETURN_OK;
2218}
2219
2220//To set Band Steering AP group
2221//To-do
2222INT wifi_setBandSteeringApGroup(char *ApGroup)
2223{
2224 return RETURN_OK;
2225}
2226
developer1e5aa162022-09-13 16:06:24 +08002227INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2228{
2229 char config_file[128] = {'\0'};
2230 char buf[128] = {'\0'};
2231
2232 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2233 if (dtimInterval == NULL)
2234 return RETURN_ERR;
2235
2236 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2237 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2238
2239 if (strlen(buf) == 0) {
2240 *dtimInterval = 2;
2241 } else {
2242 *dtimInterval = strtoul(buf, NULL, 10);
2243 }
2244
2245 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2246 return RETURN_OK;
2247}
2248
developer06a01d92022-09-07 16:32:39 +08002249INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2250{
developer5f222492022-09-13 15:21:52 +08002251 struct params params={0};
2252 char config_file[MAX_BUF_SIZE] = {'\0'};
2253 char buf[MAX_BUF_SIZE] = {'\0'};
2254
2255 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2256 if (dtimInterval < 1 || dtimInterval > 255) {
2257 return RETURN_ERR;
2258 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2259 }
2260
2261 params.name = "dtim_period";
2262 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2263 params.value = buf;
2264
2265 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2266 wifi_hostapdWrite(config_file, &params, 1);
2267 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2268
2269 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2270 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002271}
2272
2273//Check if the driver support the Dfs
2274INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2275{
2276 if (NULL == output_bool)
2277 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002278 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002279 return RETURN_OK;
2280}
2281
2282//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.
2283//The value of this parameter is a comma seperated list of channel number
2284INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2285{
2286 if (NULL == output_pool)
2287 return RETURN_ERR;
2288 if (radioIndex==1)
2289 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2290 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2291
2292 return RETURN_OK;
2293}
2294
2295INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2296{
2297 //Set to wifi config. And apply instantly.
2298 return RETURN_OK;
2299}
2300
2301INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2302{
2303 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2304 return RETURN_ERR;
2305 *output_interval_seconds=1800;
2306 *output_dwell_milliseconds=40;
2307
2308 return RETURN_OK;
2309}
2310
2311INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2312{
2313 //Set to wifi config. And apply instantly.
2314 return RETURN_OK;
2315}
2316
2317//Get the Dfs enable status
2318INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2319{
developer9964b5b2022-09-13 15:59:34 +08002320 char buf[16] = {0};
2321 FILE *f = NULL;
2322 wifi_band band;
2323
2324 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2325
2326 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002327 if (NULL == output_bool)
2328 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002329
2330 band = wifi_index_to_band(radioIndex);
2331 if (band != band_5)
2332 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002333
developer9964b5b2022-09-13 15:59:34 +08002334 f = fopen(DFS_ENABLE_FILE, "r");
2335 if (f != NULL) {
2336 fgets(buf, 2, f);
2337 if (strncmp(buf, "0", 0) == 0)
2338 *output_bool = FALSE;
2339 fclose(f);
2340 }
2341 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002342 return RETURN_OK;
2343}
2344
2345//Set the Dfs enable status
2346INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2347{
developer9964b5b2022-09-13 15:59:34 +08002348 char buf[128] = {0};
2349 char config_file[128] = {0};
2350 FILE *f = NULL;
2351 struct params params={0};
2352 wifi_band band;
2353
2354 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2355
2356 band = wifi_index_to_band(radioIndex);
2357 if (band != band_5)
2358 return RETURN_OK;
2359
2360 f = fopen(DFS_ENABLE_FILE, "w");
2361 if (f == NULL)
2362 return RETURN_ERR;
2363 fprintf(f, "%d", enable);
2364 fclose(f);
2365
2366 params.name = "acs_exclude_dfs";
2367 sprintf(buf, "%d", enable?"1":"0");
2368 params.value = buf;
2369 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2370 wifi_hostapdWrite(config_file, &params, 1);
2371 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2372
2373 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2374
2375 wifi_reloadAp(radioIndex);
2376
2377 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002378}
2379
2380//Check if the driver support the AutoChannelRefreshPeriod
2381INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2382{
2383 if (NULL == output_bool)
2384 return RETURN_ERR;
2385 *output_bool=FALSE; //not support
2386
2387 return RETURN_OK;
2388}
2389
2390//Get the ACS refresh period in seconds
2391INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2392{
2393 if (NULL == output_ulong)
2394 return RETURN_ERR;
2395 *output_ulong=300;
2396
2397 return RETURN_OK;
2398}
2399
2400//Set the ACS refresh period in seconds
2401INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2402{
2403 return RETURN_ERR;
2404}
2405
2406//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2407//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.
2408INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2409{
developer70490032022-09-13 15:45:20 +08002410 char cmd[128] = {0}, buf[64] = {0};
2411 char interface_name[64] = {0};
2412 int ret = 0, len=0;
2413 BOOL radio_enable = FALSE;
2414
2415 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2416
developer06a01d92022-09-07 16:32:39 +08002417 if (NULL == output_string)
2418 return RETURN_ERR;
2419
developer70490032022-09-13 15:45:20 +08002420 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2421 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002422
developer70490032022-09-13 15:45:20 +08002423 if (radio_enable != TRUE)
2424 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002425
developer70490032022-09-13 15:45:20 +08002426 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002427 ret = _syscmd(cmd, buf, sizeof(buf));
2428 len = strlen(buf);
2429 if((ret != 0) || (len == 0))
2430 {
2431 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2432 return RETURN_ERR;
2433 }
2434
2435 buf[len-1] = '\0';
2436 snprintf(output_string, 64, "%sMHz", buf);
2437 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2438
2439#if 0
2440 //TODO: revisit below implementation
2441 char output_buf[8]={0};
2442 char bw_value[10];
2443 char config_file[MAX_BUF_SIZE] = {0};
2444
2445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2446 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2447 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2448 readBandWidth(radioIndex,bw_value);
2449
2450 if(strstr (output_buf,"0") != NULL )
2451 {
2452 strcpy(output_string,bw_value);
2453 }
2454 else if (strstr (output_buf,"1") != NULL)
2455 {
2456 strcpy(output_string,"80MHz");
2457 }
2458 else if (strstr (output_buf,"2") != NULL)
2459 {
2460 strcpy(output_string,"160MHz");
2461 }
2462 else if (strstr (output_buf,"3") != NULL)
2463 {
2464 strcpy(output_string,"80+80");
2465 }
2466 else
2467 {
2468 strcpy(output_string,"Auto");
2469 }
2470 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2471#endif
2472
2473 return RETURN_OK;
2474}
2475
2476//Set the Operating Channel Bandwidth.
2477INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181 //AP only
2478{
2479 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2480 char config_file[MAX_BUF_SIZE];
2481 struct params params[4];
2482 struct params *pptr = params;
2483
2484 if(NULL == output_string)
2485 return RETURN_ERR;
2486
2487 pptr->name = "vht_oper_chwidth";
2488 if(strcmp(output_string,"20MHz") == 0) // This piece of code only support for wifi hal api's validation
2489 pptr->value="0";
2490 else if(strcmp(output_string,"40MHz") == 0)
2491 pptr->value="0";
2492 else if(strcmp(output_string,"80MHz") == 0)
2493 pptr->value="1";
2494 else if(strcmp(output_string,"160MHz") == 0)
2495 pptr->value="2";
2496 else if(strcmp(output_string,"80+80") == 0)
2497 pptr->value="3";
2498 else
2499 {
2500 printf("Invalid Bandwidth \n");
2501 return RETURN_ERR;
2502 }
2503
2504 pptr++; // added vht_oper_chwidth
2505
2506 if(radioIndex == 1)
2507 {
2508 pptr->name= "ieee80211n";
2509 if(strcmp(output_string,"20MHz") == 0)
2510 pptr->value="0";
2511 else if(strcmp(output_string,"40MHz") == 0)
2512 pptr->value="1";
2513 else if(strcmp(output_string,"80MHz") == 0)
2514 pptr->value="1";
2515 else
2516 pptr->value="0";
2517
2518 pptr++; // added ieee80211n
2519
2520 pptr->name="ieee80211ac";
2521 if(strcmp(output_string,"80MHz") == 0)
2522 pptr->value="1";
2523 else
2524 pptr->value="0";
2525 pptr++;
2526 }
2527
2528 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2529 {
2530 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2531 wifi_hostapdWrite(config_file, params, (pptr - params));
2532 }
2533
2534 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2535 return RETURN_OK;
2536}
2537
2538//Getting current radio extension channel
2539INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2540{
2541 CHAR buf[150] = {0};
2542 CHAR cmd[150] = {0};
2543 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2544 _syscmd(cmd, buf, sizeof(buf));
2545 if(NULL != strstr(buf,"HT40+"))
2546 strcpy(Value,"AboveControlChannel");
2547 else if(NULL != strstr(buf,"HT40-"))
2548 strcpy(Value,"BelowControlChannel");
2549 return RETURN_OK;
2550}
2551
2552//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2553//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.
2554INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2555{
2556 if (NULL == output_string)
2557 return RETURN_ERR;
2558
2559 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2560#if 0
2561 CHAR Value[100] = {0};
2562 if (NULL == output_string)
2563 return RETURN_ERR;
2564 if(radioIndex == 0)
2565 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2566 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2567 {
2568 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2569 if(strcmp(Value,"40MHz") == 0)
2570 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2571 else
2572 strcpy(Value,"Auto");
2573 }
2574 strcpy(output_string,Value);
2575#endif
2576
2577 return RETURN_OK;
2578}
2579
2580//Set the extension channel.
2581INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2582{
2583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2584 struct params params={'\0'};
2585 char config_file[MAX_BUF_SIZE] = {0};
2586 char ext_channel[127]={'\0'};
2587
2588 params.name = "ht_capab";
2589
2590 if(radioIndex == 0)
2591 {
2592 if(NULL!= strstr(string,"Above"))
2593 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40+]");
2594 else if(NULL!= strstr(string,"Below"))
2595 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40-]");
2596 else
2597 strcpy(ext_channel, HOSTAPD_HT_CAPAB_20);
2598 }
2599 else if(radioIndex == 1)
2600 {
2601 if(NULL!= strstr(string,"Above"))
2602 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40+]");
2603 else if(NULL!= strstr(string,"Below"))
2604 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40-]");
2605 else
2606 strcpy(ext_channel, HOSTAPD_HT_CAPAB_20);
2607 }
2608
2609 params.value = ext_channel;
2610 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2611 {
2612 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2613 wifi_hostapdWrite(config_file, &params, 1);
2614 }
2615
2616 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2617 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2618 return RETURN_OK;
2619}
2620
2621//Get the guard interval value. eg "400nsec" or "800nsec"
2622//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.
2623INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2624{
developer454b9462022-09-13 15:29:16 +08002625 wifi_guard_interval_t GI;
2626
2627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2628
2629 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002630 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002631
2632 if (GI == wifi_guard_interval_400)
2633 strcpy(output_string, "400nsec");
2634 else if (GI == wifi_guard_interval_800)
2635 strcpy(output_string, "800nsec");
2636 else if (GI == wifi_guard_interval_1600)
2637 strcpy(output_string, "1600nsec");
2638 else if (GI == wifi_guard_interval_3200)
2639 strcpy(output_string, "3200nsec");
2640 else
2641 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002642
developer454b9462022-09-13 15:29:16 +08002643 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002644 return RETURN_OK;
2645}
2646
2647//Set the guard interval value.
2648INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2649{
developer454b9462022-09-13 15:29:16 +08002650 wifi_guard_interval_t GI;
2651 int ret = 0;
2652
2653 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2654
2655 if (strcmp(string, "400nsec") == 0)
2656 GI = wifi_guard_interval_400;
2657 else if (strcmp(string , "800nsec") == 0 || strcmp(string, "auto") == 0)
2658 GI = wifi_guard_interval_800;
2659 else if (strcmp(string , "1600nsec") == 0)
2660 GI = wifi_guard_interval_1600;
2661 else if (strcmp(string , "3200nsec") == 0)
2662 GI = wifi_guard_interval_3200;
2663
2664 ret = wifi_setGuardInterval(radioIndex, GI);
2665
2666 if (ret == RETURN_ERR) {
2667 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2668 return RETURN_ERR;
2669 }
2670
2671 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2672 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002673}
2674
2675//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2676INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2677{
2678 if (NULL == output_int)
2679 return RETURN_ERR;
2680 *output_int=(radioIndex==0)?1:3;
2681
2682 return RETURN_OK;
2683}
2684
2685//Set the Modulation Coding Scheme index
2686INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2687{
2688 return RETURN_ERR;
2689}
2690
2691//Get supported Transmit Power list, eg : "0,25,50,75,100"
2692//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.
2693INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2694{
2695 if (NULL == output_list)
2696 return RETURN_ERR;
2697 snprintf(output_list, 64,"0,25,50,75,100");
2698 return RETURN_OK;
2699}
2700
developera5005b62022-09-13 15:43:35 +08002701//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002702//The transmite power level is in units of full power for this radio.
2703INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2704{
2705 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002706 char buf[16]={0};
2707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002708
developera5005b62022-09-13 15:43:35 +08002709 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002710 return RETURN_ERR;
2711
developera5005b62022-09-13 15:43:35 +08002712 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 +08002713 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002714
developera5005b62022-09-13 15:43:35 +08002715 *output_ulong = strtol(buf, NULL, 10);
2716
2717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002718 return RETURN_OK;
2719}
2720
2721//Set Transmit Power
2722//The transmite power level is in units of full power for this radio.
2723INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2724{
developera5005b62022-09-13 15:43:35 +08002725 char *support;
developer06a01d92022-09-07 16:32:39 +08002726 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002727 char buf[128]={0};
2728 char txpower_str[64] = {0};
2729 int txpower = 0;
2730 int maximum_tx = 0;
2731
2732 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002733
developera5005b62022-09-13 15:43:35 +08002734 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 +08002735 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002736 maximum_tx = strtol(buf, NULL, 10);
2737
2738 // Get the Tx power supported list and check that is the input in the list
2739 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2740 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2741 support = strtok(buf, ",");
2742 while(true)
2743 {
2744 if(support == NULL) { // input not in the list
2745 wifi_dbg_printf("Input value is invalid.\n");
2746 return RETURN_ERR;
2747 }
2748 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2749 break;
2750 }
2751 support = strtok(NULL, ",");
2752 }
2753 txpower = TransmitPower*maximum_tx/100;
2754 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2755 _syscmd(cmd, buf, sizeof(buf));
2756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002757
2758 return RETURN_OK;
2759}
2760
2761//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2762INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2763{
2764 if (NULL == Supported)
2765 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002766 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002767
2768 return RETURN_OK;
2769}
2770
2771//Get 80211h feature enable
2772INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2773{
developer3885fec2022-09-13 15:13:47 +08002774 char buf[64]={'\0'};
2775 char config_file[64] = {'\0'};
2776
2777 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2778 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002779 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002780
2781 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2782 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002783
developer3885fec2022-09-13 15:13:47 +08002784 if (strncmp(buf, "1", 1) == 0)
2785 *enable = TRUE;
2786 else
2787 *enable = FALSE;
2788
2789 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002790 return RETURN_OK;
2791}
2792
2793//Set 80211h feature enable
2794INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2795{
developer3885fec2022-09-13 15:13:47 +08002796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2797 struct params params={'\0'};
2798 char config_file[MAX_BUF_SIZE] = {0};
2799
2800 params.name = "ieee80211h";
2801
2802 if (enable) {
2803 params.value = "1";
2804 } else {
2805 params.value = "0";
2806 }
2807
2808 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2809 wifi_hostapdWrite(config_file, &params, 1);
2810
2811 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2812 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2813 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002814}
2815
2816//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.
2817INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2818{
2819 if (NULL == output)
2820 return RETURN_ERR;
2821 *output=100;
2822
2823 return RETURN_OK;
2824}
2825
2826//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.
2827INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2828{
2829 if (NULL == output)
2830 return RETURN_ERR;
2831 *output = -99;
2832
2833 return RETURN_OK;
2834}
2835
2836INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2837{
2838 return RETURN_ERR;
2839}
2840
2841
2842//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2843INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2844{
developer5f222492022-09-13 15:21:52 +08002845 char cmd[MAX_BUF_SIZE]={'\0'};
2846 char buf[MAX_CMD_SIZE]={'\0'};
2847
2848 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2849 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08002850 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002851
2852 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
2853 _syscmd(cmd, buf, sizeof(buf));
2854 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08002855
developer5f222492022-09-13 15:21:52 +08002856 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002857 return RETURN_OK;
2858}
2859
2860INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
2861{
developer5f222492022-09-13 15:21:52 +08002862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2863 struct params params={'\0'};
2864 char buf[MAX_BUF_SIZE] = {'\0'};
2865 char config_file[MAX_BUF_SIZE] = {'\0'};
2866
2867 params.name = "beacon_int";
2868 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
2869 params.value = buf;
2870
2871 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2872 wifi_hostapdWrite(config_file, &params, 1);
2873
2874 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2875 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2876 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002877}
2878
2879//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.
2880INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
2881{
developer06a01d92022-09-07 16:32:39 +08002882 //TODO: need to revisit below implementation
2883 char *temp;
developere9d0abd2022-09-13 15:40:57 +08002884 char temp_output[128] = {0};
2885 char temp_TransmitRates[64] = {0};
2886 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08002887
2888 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2889 if (NULL == output)
2890 return RETURN_ERR;
2891 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08002892 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
2893
2894 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
2895 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
2896 } else {
2897 temp = strtok(temp_TransmitRates," ");
2898 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08002899 {
developere9d0abd2022-09-13 15:40:57 +08002900 // Convert 100 kbps to Mbps
2901 temp[strlen(temp)-1]=0;
2902 if((temp[0]=='5') && (temp[1]=='\0'))
2903 {
2904 temp="5.5";
2905 }
2906 strcat(temp_output,temp);
2907 temp = strtok(NULL," ");
2908 if(temp!=NULL)
2909 {
2910 strcat(temp_output,",");
2911 }
developer06a01d92022-09-07 16:32:39 +08002912 }
developere9d0abd2022-09-13 15:40:57 +08002913 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08002914 }
developer06a01d92022-09-07 16:32:39 +08002915 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002916 return RETURN_OK;
2917}
2918
2919INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
2920{
2921 char *temp;
2922 char temp1[128];
2923 char temp_output[128];
2924 char temp_TransmitRates[128];
2925 char set[128];
2926 char sub_set[128];
2927 int set_count=0,subset_count=0;
2928 int set_index=0,subset_index=0;
2929 char *token;
2930 int flag=0, i=0;
2931 struct params params={'\0'};
2932 char config_file[MAX_BUF_SIZE] = {0};
2933
2934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2935 if(NULL == TransmitRates)
2936 return RETURN_ERR;
2937 strcpy(sub_set,TransmitRates);
2938
2939 //Allow only supported Data transmit rate to be set
2940 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
2941 token = strtok(sub_set,",");
2942 while( token != NULL ) /* split the basic rate to be set, by comma */
2943 {
2944 sub_set[subset_count]=atoi(token);
2945 subset_count++;
2946 token=strtok(NULL,",");
2947 }
2948 token=strtok(set,",");
2949 while(token!=NULL) /* split the supported rate by comma */
2950 {
2951 set[set_count]=atoi(token);
2952 set_count++;
2953 token=strtok(NULL,",");
2954 }
2955 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
2956 {
2957 for(set_index=0;set_index < set_count;set_index++)
2958 {
2959 flag=0;
2960 if(sub_set[subset_index]==set[set_index])
2961 break;
2962 else
2963 flag=1; /* No match found */
2964 }
2965 if(flag==1)
2966 return RETURN_ERR; //If value not found return Error
2967 }
2968 strcpy(temp_TransmitRates,TransmitRates);
2969
2970 for(i=0;i<strlen(temp_TransmitRates);i++)
2971 {
2972 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
2973 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
2974 {
2975 continue;
2976 }
2977 else
2978 {
2979 return RETURN_ERR;
2980 }
2981 }
2982 strcpy(temp_output,"");
2983 temp = strtok(temp_TransmitRates,",");
2984 while(temp!=NULL)
2985 {
2986 strcpy(temp1,temp);
2987 if(radioIndex==1)
2988 {
2989 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
2990 {
2991 return RETURN_ERR;
2992 }
2993 }
2994
2995 if(strcmp(temp,"5.5")==0)
2996 {
2997 strcpy(temp1,"55");
2998 }
2999 else
3000 {
3001 strcat(temp1,"0");
3002 }
3003 strcat(temp_output,temp1);
3004 temp = strtok(NULL,",");
3005 if(temp!=NULL)
3006 {
3007 strcat(temp_output," ");
3008 }
3009 }
3010 strcpy(TransmitRates,temp_output);
3011
3012 params.name= "basic_rates";
3013 params.value =TransmitRates;
3014
3015 wifi_dbg_printf("\n%s:",__func__);
3016 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3017 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3018 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3019 wifi_hostapdWrite(config_file,&params,1);
3020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3021 return RETURN_OK;
3022}
3023
3024//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3025INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3026{
3027 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3028 FILE *fp = NULL;
3029 char path[256] = {0}, output_string[256] = {0};
3030 int count = 0;
3031 char *interface = NULL;
3032
3033 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3034 if (fp == NULL)
3035 {
3036 printf("Failed to run command in Function %s\n", __FUNCTION__);
3037 return RETURN_ERR;
3038 }
3039 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3040 {
3041 interface = strchr(path, '=');
3042
3043 if (interface != NULL)
3044 {
3045 strcpy(output_string, interface + 1);
3046 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3047 interface_name[count] = output_string[count];
3048
3049 interface_name[count] = '\0';
3050 }
3051 }
3052 pclose(fp);
3053 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3054 return RETURN_OK;
3055}
3056
3057INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3058{
3059 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3060 output_struct->radio_BytesSent = 0;
3061 output_struct->radio_BytesReceived = 0;
3062 output_struct->radio_PacketsSent = 0;
3063 output_struct->radio_PacketsReceived = 0;
3064 output_struct->radio_ErrorsSent = 0;
3065 output_struct->radio_ErrorsReceived = 0;
3066 output_struct->radio_DiscardPacketsSent = 0;
3067 output_struct->radio_DiscardPacketsReceived = 0;
3068 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3069 return RETURN_OK;
3070}
3071
3072
3073INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3074{
3075 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3076 CHAR buf[MAX_CMD_SIZE] = {0};
3077 CHAR Value[MAX_BUF_SIZE] = {0};
3078 FILE *fp = NULL;
3079
3080 if (ifname == NULL || strlen(ifname) <= 1)
3081 return RETURN_OK;
3082
3083 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3084 system(buf);
3085
3086 fp = fopen("/tmp/Radio_Stats.txt", "r");
3087 if(fp == NULL)
3088 {
3089 printf("/tmp/Radio_Stats.txt not exists \n");
3090 return RETURN_ERR;
3091 }
3092 fclose(fp);
3093
3094 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3095 File_Reading(buf, Value);
3096 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3097
3098 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3099 File_Reading(buf, Value);
3100 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3101
3102 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3103 File_Reading(buf, Value);
3104 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3105
3106 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3107 File_Reading(buf, Value);
3108 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3109
3110 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3111 File_Reading(buf, Value);
3112 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3113
3114 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3115 File_Reading(buf, Value);
3116 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3117
3118 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3119 File_Reading(buf, Value);
3120 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3121
3122 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3123 File_Reading(buf, Value);
3124 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3125
3126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3127 return RETURN_OK;
3128}
3129
3130INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3131{
3132 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3133 CHAR buf[MAX_CMD_SIZE] = {0};
3134 FILE *fp = NULL;
3135 INT count = 0;
3136
3137 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3138 {
3139 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3140 File_Reading(buf, status);
3141 }
3142 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3143 return RETURN_OK;
3144}
3145
3146//Get detail radio traffic static info
3147INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3148{
3149
3150#if 0
3151 //ifconfig radio_x
3152 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3153 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3154 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3155 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3156
3157 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3158 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3159 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.
3160 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.
3161
3162 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3163 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].
3164 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3165 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.
3166 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
3167 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
3168 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
3169 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
3170 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
3171
3172 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
3173 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
3174 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
3175 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.
3176
3177 return RETURN_OK;
3178#endif
3179
3180 CHAR private_interface_name[MAX_BUF_SIZE] = {0}, public_interface_name[MAX_BUF_SIZE] = {0};
3181 CHAR private_interface_status[MAX_BUF_SIZE] = {0}, public_interface_status[MAX_BUF_SIZE] = {0};
3182 char buf[MAX_BUF_SIZE] = {0};
3183 char cmd[MAX_CMD_SIZE] = {0};
3184 wifi_radioTrafficStats2_t private_radioTrafficStats = {0}, public_radioTrafficStats = {0};
3185
3186 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3187 if (NULL == output_struct)
3188 return RETURN_ERR;
3189
3190 if (radioIndex == 0) //2.4GHz ?
3191 {
3192
3193 GetInterfaceName(private_interface_name, "/nvram/hostapd0.conf");
3194
3195 GetIfacestatus(private_interface_name, private_interface_status);
3196
3197 sprintf(cmd, "%s", "cat /nvram/hostapd0.conf | grep bss=");
3198 File_Reading(cmd, buf);
3199
3200 if (buf[0] == '#')
3201 {
3202 GetInterfaceName(public_interface_name, "/nvram/hostapd4.conf");
3203 }
3204 else
3205 {
3206 GetInterfaceName_virtualInterfaceName_2G(public_interface_name);
3207 }
3208
3209 GetIfacestatus(public_interface_name, public_interface_status);
3210
3211 if (strcmp(private_interface_status, "1") == 0)
3212 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
3213 else
3214 wifi_halGetIfStatsNull(&private_radioTrafficStats);
3215
3216 if (strcmp(public_interface_status, "1") == 0)
3217 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
3218 else
3219 wifi_halGetIfStatsNull(&public_radioTrafficStats);
3220 }
3221 else if (radioIndex == 1) //5GHz ?
3222 {
3223 GetInterfaceName(private_interface_name, "/nvram/hostapd1.conf");
3224 GetIfacestatus(private_interface_name, private_interface_status);
3225
3226 GetInterfaceName(public_interface_name, "/nvram/hostapd5.conf");
3227 GetIfacestatus(public_interface_name, public_interface_status);
3228
3229 if (strcmp(private_interface_status, "1") == 0)
3230 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
3231 else
3232 wifi_halGetIfStatsNull(&private_radioTrafficStats);
3233
3234 if (strcmp(public_interface_status, "1") == 0)
3235 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
3236 else
3237 wifi_halGetIfStatsNull(&public_radioTrafficStats);
3238 }
3239
3240 output_struct->radio_BytesSent = private_radioTrafficStats.radio_BytesSent + public_radioTrafficStats.radio_BytesSent;
3241 output_struct->radio_BytesReceived = private_radioTrafficStats.radio_BytesReceived + public_radioTrafficStats.radio_BytesReceived;
3242 output_struct->radio_PacketsSent = private_radioTrafficStats.radio_PacketsSent + public_radioTrafficStats.radio_PacketsSent;
3243 output_struct->radio_PacketsReceived = private_radioTrafficStats.radio_PacketsReceived + public_radioTrafficStats.radio_PacketsReceived;
3244 output_struct->radio_ErrorsSent = private_radioTrafficStats.radio_ErrorsSent + public_radioTrafficStats.radio_ErrorsSent;
3245 output_struct->radio_ErrorsReceived = private_radioTrafficStats.radio_ErrorsReceived + public_radioTrafficStats.radio_ErrorsReceived;
3246 output_struct->radio_DiscardPacketsSent = private_radioTrafficStats.radio_DiscardPacketsSent + public_radioTrafficStats.radio_DiscardPacketsSent;
3247 output_struct->radio_DiscardPacketsReceived = private_radioTrafficStats.radio_DiscardPacketsReceived + public_radioTrafficStats.radio_DiscardPacketsReceived;
3248
3249 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3250 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].
3251 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3252 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.
3253 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
3254 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
3255 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
3256 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
3257 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
3258
3259 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
3260 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
3261 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
3262 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.
3263
3264 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3265
3266 return RETURN_OK;
3267}
3268
3269//Set radio traffic static Measureing rules
3270INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3271{
3272 //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
3273 // Else, save the MeasuringRate and MeasuringInterval for future usage
3274
3275 return RETURN_OK;
3276}
3277
3278//To start or stop RadioTrafficStats
3279INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3280{
3281 //zqiu: If the RadioTrafficStats process running
3282 // if(enable)
3283 // return RETURN_OK.
3284 // else
3285 // Stop RadioTrafficStats process
3286 // Else
3287 // if(enable)
3288 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3289 // else
3290 // return RETURN_OK.
3291
3292 return RETURN_OK;
3293}
3294
3295//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
3296INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3297{
3298 //zqiu: Please ignor signalIndex.
3299 if (NULL == SignalLevel)
3300 return RETURN_ERR;
3301 *SignalLevel=(radioIndex==0)?-19:-19;
3302
3303 return RETURN_OK;
3304}
3305
3306//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3307INT wifi_applyRadioSettings(INT radioIndex)
3308{
3309 return RETURN_OK;
3310}
3311
3312//Get the radio index assocated with this SSID entry
3313INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3314{
3315 if (NULL == radioIndex)
3316 return RETURN_ERR;
3317 *radioIndex=ssidIndex%2;
3318
3319 return RETURN_OK;
3320}
3321
3322//Device.WiFi.SSID.{i}.Enable
3323//Get SSID enable configuration parameters (not the SSID enable status)
3324INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3325{
3326 if (NULL == output_bool)
3327 return RETURN_ERR;
3328
3329 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3330 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3331 return wifi_getApEnable(ssidIndex, output_bool);
3332}
3333
3334//Device.WiFi.SSID.{i}.Enable
3335//Set SSID enable configuration parameters
3336INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3337{
3338 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3339 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3340 return wifi_setApEnable(ssidIndex, enable);
3341}
3342
3343//Device.WiFi.SSID.{i}.Status
3344//Get the SSID enable status
3345INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3346{
3347 char cmd[MAX_CMD_SIZE]={0};
3348 char buf[MAX_BUF_SIZE]={0};
3349 BOOL output_bool;
3350
3351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3352 if (NULL == output_string)
3353 return RETURN_ERR;
3354 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3355 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3356
3357 wifi_getApEnable(ssidIndex,&output_bool);
3358 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3359
3360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3361 return RETURN_OK;
3362}
3363
3364// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3365INT wifi_getSSIDName(INT apIndex, CHAR *output)
3366{
3367 char config_file[MAX_BUF_SIZE] = {0};
3368
3369 if (NULL == output)
3370 return RETURN_ERR;
3371
3372 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3373 wifi_hostapdRead(config_file,"ssid",output,32);
3374
3375 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3376 return RETURN_OK;
3377}
3378
3379// Set a max 32 byte string and sets an internal variable to the SSID name
3380INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3381{
3382 char str[MAX_BUF_SIZE]={'\0'};
3383 char cmd[MAX_CMD_SIZE]={'\0'};
3384 struct params params;
3385 char config_file[MAX_BUF_SIZE] = {0};
3386
3387 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3388 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3389 return RETURN_ERR;
3390
3391 params.name = "ssid";
3392 params.value = ssid_string;
3393 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3394 wifi_hostapdWrite(config_file, &params, 1);
3395 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3396 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3397
3398 return RETURN_OK;
3399}
3400
3401//Get the BSSID
3402INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3403{
3404 char cmd[MAX_CMD_SIZE]="";
3405
3406 if (NULL == output_string)
3407 return RETURN_ERR;
3408
3409 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3410 {
3411 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3412 _syscmd(cmd, output_string, 64);
3413 return RETURN_OK;
3414 }
3415 strncpy(output_string, "\0", 1);
3416
3417 return RETURN_ERR;
3418}
3419
3420//Get the MAC address associated with this Wifi SSID
3421INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3422{
3423 wifi_getBaseBSSID(ssidIndex,output_string);
3424 return RETURN_OK;
3425}
3426
3427//Get the basic SSID traffic static info
3428//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3429//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3430INT wifi_applySSIDSettings(INT ssidIndex)
3431{
3432 BOOL status = false;
3433 char cmd[MAX_CMD_SIZE] = {0};
3434 char buf[MAX_CMD_SIZE] = {0};
3435 int apIndex, ret;
3436 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3437
3438 wifi_getApEnable(ssidIndex,&status);
3439 // Do not apply when ssid index is disabled
3440 if (status == false)
3441 return RETURN_OK;
3442
3443 /* Doing full remove and add for ssid Index
3444 * Not all hostapd options are supported with reload
3445 * for example macaddr_acl
3446 */
3447 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3448 return RETURN_ERR;
3449
3450 ret = wifi_setApEnable(ssidIndex,true);
3451
3452 /* Workaround for hostapd issue with multiple bss definitions
3453 * when first created interface will be removed
3454 * then all vaps other vaps on same phy are removed
3455 * after calling setApEnable to false readd all enabled vaps */
3456 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3457 apIndex = 2*i+radioIndex;
3458 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3459 _syscmd(cmd, buf, sizeof(buf));
3460 if(*buf == '1')
3461 wifi_setApEnable(apIndex, true);
3462 }
3463
3464 return ret;
3465}
3466
developera3c68b92022-09-13 15:27:29 +08003467struct channels_noise {
3468 int channel;
3469 int noise;
3470};
3471
3472// Return noise array for each channel
3473int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3474{
3475 FILE *f = NULL;
3476 char cmd[128] = {0};
3477 char *line = NULL;
3478 size_t len = 0;
3479 ssize_t read = 0;
3480 int tmp = 0, arr_index = -1;
3481
3482 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3483
3484 if ((f = popen(cmd, "r")) == NULL) {
3485 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3486 return RETURN_ERR;
3487 }
3488 line = malloc(sizeof(char) * 256);
3489 while((read = getline(&line, &len, f)) != -1) {
3490 sscanf(line, "%d", &tmp);
3491 if (tmp > 0) { // channel frequency, the first line must be frequency
3492 arr_index++;
3493 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3494 } else { // noise
3495 channels_noise_arr[arr_index].noise = tmp;
3496 }
3497 }
3498 free(line);
3499 pclose(f);
3500 return RETURN_OK;
3501}
3502
developer06a01d92022-09-07 16:32:39 +08003503//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3504//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3505INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3506{
developera3c68b92022-09-13 15:27:29 +08003507 int index = -1;
3508 wifi_neighbor_ap2_t *scan_array = NULL;
3509 char cmd[256]={0};
3510 char buf[128]={0};
3511 char file_name[32] = {0};
3512 char filter_SSID[32] = {0};
3513 int freq=0;
3514 FILE *f = NULL;
3515 size_t len=0;
3516 ssize_t read = 0;
3517 char *line =NULL;
3518 // int noise_arr[channels_num] = {0};
3519 int channels_num = 0;
3520 int vht_channel_width = 0;
3521 bool get_nosie_ret = false;
3522 bool filter_enable = false;
3523 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003524
3525 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003526
3527 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3528 f = fopen(file_name, "r");
3529 if (f != NULL) {
3530 fgets(filter_SSID, sizeof(file_name), f);
3531 if (strlen(filter_SSID) != 0)
3532 filter_enable = true;
3533 fclose(f);
3534 }
3535
3536 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003537 _syscmd(cmd, buf, sizeof(buf));
developera3c68b92022-09-13 15:27:29 +08003538 channels_num = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003539
developera3c68b92022-09-13 15:27:29 +08003540 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3541 get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer06a01d92022-09-07 16:32:39 +08003542
developera3c68b92022-09-13 15:27:29 +08003543 sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3544 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE160' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
3545 fprintf(stderr, "cmd: %s\n", cmd);
3546 if ((f = popen(cmd, "r")) == NULL) {
3547 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3548 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003549 }
developera3c68b92022-09-13 15:27:29 +08003550 line = malloc(sizeof(char) * 256);
3551 while ((read = getline(&line, &len, f)) != -1) {
3552 if(strstr(line, "BSS") != NULL) { // new neighbor info
3553 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3554 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3555 // 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 +08003556
developera3c68b92022-09-13 15:27:29 +08003557 if (!filter_BSS) {
3558 index++;
3559 wifi_neighbor_ap2_t *tmp;
3560 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3561 if (tmp == NULL) { // no more memory to use
3562 index--;
3563 wifi_dbg_printf("%s: realloc failed\n", __func__);
3564 break;
3565 }
3566 scan_array = tmp;
3567 }
3568 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3569
3570 filter_BSS = false;
3571 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3572 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3573 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3574 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3575 } else if (strstr(line, "freq") != NULL) {
3576 sscanf(line," freq: %d", &freq);
3577 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3578
3579 if (freq >= 2412 && freq <= 2484) {
3580 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3581 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3582 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3583 }
3584 else if (freq >= 5160 && freq <= 5805) {
3585 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3586 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3587 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3588 }
3589
3590 scan_array[index].ap_Noise = 0;
3591 if (get_nosie_ret) {
3592 for (int i = 0; i < channels_num; i++) {
3593 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3594 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3595 break;
3596 }
3597 }
3598 }
3599 } else if (strstr(line, "beacon interval") != NULL) {
3600 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3601 } else if (strstr(line, "signal") != NULL) {
3602 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3603 } else if (strstr(line,"SSID") != NULL) {
3604 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3605 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3606 filter_BSS = true;
3607 }
3608 } else if (strstr(line, "Supported rates") != NULL) {
3609 char SRate[80] = {0}, *tmp = NULL;
3610 memset(buf, 0, sizeof(buf));
3611 strcpy(SRate, line);
3612 tmp = strtok(SRate, ":");
3613 tmp = strtok(NULL, ":");
3614 strcpy(buf, tmp);
3615 memset(SRate, 0, sizeof(SRate));
3616
3617 tmp = strtok(buf, " \n");
3618 while (tmp != NULL) {
3619 strcat(SRate, tmp);
3620 if (SRate[strlen(SRate) - 1] == '*') {
3621 SRate[strlen(SRate) - 1] = '\0';
3622 }
3623 strcat(SRate, ",");
3624
3625 tmp = strtok(NULL, " \n");
3626 }
3627 SRate[strlen(SRate) - 1] = '\0';
3628 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3629 } else if (strstr(line, "DTIM") != NULL) {
3630 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3631 } else if (strstr(line, "VHT capabilities") != NULL) {
3632 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3633 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3634 } else if (strstr(line, "HT capabilities") != NULL) {
3635 strcat(scan_array[index].ap_SupportedStandards, ",n");
3636 strcpy(scan_array[index].ap_OperatingStandards, "n");
3637 } else if (strstr(line, "VHT operation") != NULL) {
3638 read = getline(&line, &len, f);
3639 sscanf(line," * channel width: %d", &vht_channel_width);
3640 if(vht_channel_width == 1) {
3641 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3642 } else {
3643 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3644 }
3645 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3646 continue;
3647 } else if (strstr(line, "HT operation") != NULL) {
3648 read = getline(&line, &len, f);
3649 sscanf(line," * secondary channel offset: %s", &buf);
3650 if (!strcmp(buf, "above")) {
3651 //40Mhz +
3652 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3653 }
3654 else if (!strcmp(buf, "below")) {
3655 //40Mhz -
3656 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3657 } else {
3658 //20Mhz
3659 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3660 }
3661 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3662 continue;
3663 } else if (strstr(line, "HE capabilities") != NULL) {
3664 strncat(scan_array[index].ap_SupportedStandards, ",ax", strlen(",ax"));
3665 strncpy(scan_array[index].ap_OperatingStandards, "ax", strlen("ax"));
3666 } else if (strstr(line, "HE PHY Capabilities") != NULL) {
3667 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3668 if (strstr(line, "HE40/2.4GHz") != NULL)
3669 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS", strlen("11AXHE40PLUS"));
3670 else
3671 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20", strlen("11AXHE20"));
3672 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
3673 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80", strlen("11AXHE80")); // AP must always support
3674 read = getline(&line, &len, f);
3675 if (strstr(line, "HE160/5GHz") != NULL)
3676 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160", strlen("11AXHE160"));
3677 }
3678 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3679 continue;
3680 } else if (strstr(line, "WPA") != NULL) {
3681 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3682 } else if (strstr(line, "RSN") != NULL) {
3683 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3684 } else if (strstr(line, "Group cipher") != NULL) {
3685 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3686 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3687 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3688 }
3689 }
3690 }
3691
3692 if (!filter_BSS) {
3693 *output_array_size = index + 1;
3694 } else {
3695 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3696 *output_array_size = index;
3697 }
3698 *neighbor_ap_array = scan_array;
3699 free(line);
3700 pclose(f);
developer06a01d92022-09-07 16:32:39 +08003701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003702 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003703}
3704
3705//>> Deprecated: used for old RDKB code.
3706INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3707{
3708 INT status = RETURN_ERR;
3709
3710 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3711 output_struct->wifi_PLCPErrorCount = 0;
3712 output_struct->wifi_FCSErrorCount = 0;
3713 output_struct->wifi_InvalidMACCount = 0;
3714 output_struct->wifi_PacketsOtherReceived = 0;
3715 output_struct->wifi_Noise = 0;
3716 status = RETURN_OK;
3717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3718 return status;
3719}
3720
3721INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3722{
3723 char cmd[128];
3724 char buf[1280];
3725 char *pos = NULL;
3726
3727 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3728 if (NULL == output_struct)
3729 return RETURN_ERR;
3730
3731 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3732
3733 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3734 _syscmd(cmd, buf, sizeof(buf));
3735
3736 pos = buf;
3737 if ((pos = strstr(pos, "RX packets:")) == NULL)
3738 return RETURN_ERR;
3739 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3740
3741 if ((pos = strstr(pos, "TX packets:")) == NULL)
3742 return RETURN_ERR;
3743 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3744
3745 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3746 return RETURN_ERR;
3747 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3748
3749 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3750 return RETURN_ERR;
3751 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3752
3753 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3754 _syscmd(cmd, buf, sizeof(buf));
3755 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3756
3757#if 0
3758 //TODO: need to revisit below implementation
3759 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3760 char interface_name[MAX_BUF_SIZE] = {0};
3761 char interface_status[MAX_BUF_SIZE] = {0};
3762 char Value[MAX_BUF_SIZE] = {0};
3763 char buf[MAX_CMD_SIZE] = {0};
3764 char cmd[MAX_CMD_SIZE] = {0};
3765 FILE *fp = NULL;
3766
3767 if (NULL == output_struct) {
3768 return RETURN_ERR;
3769 }
3770
3771 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3772
3773 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3774 {
3775 if(apIndex == 0) //private_wifi for 2.4G
3776 {
3777 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3778 }
3779 else if(apIndex == 1) //private_wifi for 5G
3780 {
3781 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3782 }
3783 else if(apIndex == 4) //public_wifi for 2.4G
3784 {
3785 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3786 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3787 {
3788 return RETURN_ERR;
3789 }
3790 if(buf[0] == '#')//tp-link
3791 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3792 else//tenda
3793 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3794 }
3795 else if(apIndex == 5) //public_wifi for 5G
3796 {
3797 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3798 }
3799
3800 GetIfacestatus(interface_name, interface_status);
3801
3802 if(0 != strcmp(interface_status, "1"))
3803 return RETURN_ERR;
3804
3805 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3806 system(cmd);
3807
3808 fp = fopen("/tmp/SSID_Stats.txt", "r");
3809 if(fp == NULL)
3810 {
3811 printf("/tmp/SSID_Stats.txt not exists \n");
3812 return RETURN_ERR;
3813 }
3814 fclose(fp);
3815
3816 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3817 File_Reading(buf, Value);
3818 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3819
3820 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3821 File_Reading(buf, Value);
3822 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3823
3824 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3825 File_Reading(buf, Value);
3826 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3827
3828 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3829 File_Reading(buf, Value);
3830 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3831
3832 /* There is no specific parameter from caller to associate the value wifi_Associations */
3833 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3834 //_syscmd(cmd, buf, sizeof(buf));
3835 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3836 }
3837#endif
3838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3839 return RETURN_OK;
3840}
3841
3842INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3843{
3844 char interface_name[MAX_BUF_SIZE] = {0};
3845 char interface_status[MAX_BUF_SIZE] = {0};
3846 char Value[MAX_BUF_SIZE] = {0};
3847 char buf[MAX_CMD_SIZE] = {0};
3848 char cmd[MAX_CMD_SIZE] = {0};
3849 FILE *fp = NULL;
3850
3851 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3852 if (NULL == output_struct)
3853 return RETURN_ERR;
3854
3855 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3856
3857 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3858 {
3859 if(apIndex == 0) //private_wifi for 2.4G
3860 {
3861 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3862 }
3863 else if(apIndex == 1) //private_wifi for 5G
3864 {
3865 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3866 }
3867 else if(apIndex == 4) //public_wifi for 2.4G
3868 {
3869 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3870 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3871 {
3872 return RETURN_ERR;
3873 }
3874 if(buf[0] == '#')
3875 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3876 else
3877 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3878 }
3879 else if(apIndex == 5) //public_wifi for 5G
3880 {
3881 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3882 }
3883
3884 GetIfacestatus(interface_name, interface_status);
3885
3886 if(0 != strcmp(interface_status, "1"))
3887 return RETURN_ERR;
3888
3889 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3890 system(cmd);
3891
3892 fp = fopen("/tmp/SSID_Stats.txt", "r");
3893 if(fp == NULL)
3894 {
3895 printf("/tmp/SSID_Stats.txt not exists \n");
3896 return RETURN_ERR;
3897 }
3898 fclose(fp);
3899
3900 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3901 File_Reading(buf, Value);
3902 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
3903
3904 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3905 File_Reading(buf, Value);
3906 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
3907
3908 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3909 File_Reading(buf, Value);
3910 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
3911
3912 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3913 File_Reading(buf, Value);
3914 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
3915 }
3916
3917 output_struct->wifi_UnicastPacketsSent = 0;
3918 output_struct->wifi_UnicastPacketsReceived = 0;
3919 output_struct->wifi_MulticastPacketsSent = 0;
3920 output_struct->wifi_MulticastPacketsReceived = 0;
3921 output_struct->wifi_BroadcastPacketsSent = 0;
3922 output_struct->wifi_BroadcastPacketsRecevied = 0;
3923 output_struct->wifi_UnknownPacketsReceived = 0;
3924
3925 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3926 return RETURN_OK;
3927}
3928
3929INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
3930{
3931 INT status = RETURN_ERR;
3932
3933 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3934 //Below values should get updated from hal
3935 output_struct->wifi_RetransCount=0;
3936 output_struct->wifi_FailedRetransCount=0;
3937 output_struct->wifi_RetryCount=0;
3938 output_struct->wifi_MultipleRetryCount=0;
3939 output_struct->wifi_ACKFailureCount=0;
3940 output_struct->wifi_AggregatedPacketCount=0;
3941
3942 status = RETURN_OK;
3943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3944
3945 return status;
3946}
3947
3948INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
3949{
3950 INT status = RETURN_ERR;
3951 UINT index;
3952 wifi_neighbor_ap_t *pt=NULL;
3953
3954 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3955 *output_array_size=2;
3956 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
3957 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
3958 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
3959 strcpy(pt->ap_Radio,"");
3960 strcpy(pt->ap_SSID,"");
3961 strcpy(pt->ap_BSSID,"");
3962 strcpy(pt->ap_Mode,"");
3963 pt->ap_Channel=1;
3964 pt->ap_SignalStrength=0;
3965 strcpy(pt->ap_SecurityModeEnabled,"");
3966 strcpy(pt->ap_EncryptionMode,"");
3967 strcpy(pt->ap_OperatingFrequencyBand,"");
3968 strcpy(pt->ap_SupportedStandards,"");
3969 strcpy(pt->ap_OperatingStandards,"");
3970 strcpy(pt->ap_OperatingChannelBandwidth,"");
3971 pt->ap_BeaconPeriod=1;
3972 pt->ap_Noise=0;
3973 strcpy(pt->ap_BasicDataTransferRates,"");
3974 strcpy(pt->ap_SupportedDataTransferRates,"");
3975 pt->ap_DTIMPeriod=1;
3976 pt->ap_ChannelUtilization = 1;
3977 }
3978
3979 status = RETURN_OK;
3980 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3981
3982 return status;
3983}
3984
3985//----------------- AP HAL -------------------------------
3986
3987//>> Deprecated: used for old RDKB code.
3988INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
3989{
3990 if (NULL == output_ulong || NULL == output_struct)
3991 return RETURN_ERR;
3992 *output_ulong = 0;
3993 *output_struct = NULL;
3994 return RETURN_OK;
3995}
3996
3997#ifdef HAL_NETLINK_IMPL
3998static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
3999 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4000 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4001 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4002 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4003 char mac_addr[20];
4004 static int count=0;
4005 int rate=0;
4006
4007 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4008
4009 nla_parse(tb,
4010 NL80211_ATTR_MAX,
4011 genlmsg_attrdata(gnlh, 0),
4012 genlmsg_attrlen(gnlh, 0),
4013 NULL);
4014
4015 if(!tb[NL80211_ATTR_STA_INFO]) {
4016 fprintf(stderr, "sta stats missing!\n");
4017 return NL_SKIP;
4018 }
4019
4020
4021 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4022 fprintf(stderr, "failed to parse nested attributes!\n");
4023 return NL_SKIP;
4024 }
4025
4026 //devIndex starts from 1
4027 if( ++count == out->wifi_devIndex )
4028 {
4029 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4030 //Getting the mac addrress
4031 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4032
4033 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4034 fprintf(stderr, "failed to parse nested rate attributes!");
4035 return NL_SKIP;
4036 }
4037
4038 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4039 if(rinfo[NL80211_RATE_INFO_BITRATE])
4040 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4041 out->wifi_devTxRate = rate/10;
4042 }
4043
4044 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4045 fprintf(stderr, "failed to parse nested rate attributes!");
4046 return NL_SKIP;
4047 }
4048
4049 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4050 if(rinfo[NL80211_RATE_INFO_BITRATE])
4051 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4052 out->wifi_devRxRate = rate/10;
4053 }
4054 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4055 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4056
4057 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4058 count = 0; //starts the count for next cycle
4059 return NL_STOP;
4060 }
4061
4062 return NL_SKIP;
4063
4064}
4065#endif
4066
4067INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4068{
4069#ifdef HAL_NETLINK_IMPL
4070 Netlink nl;
4071 char if_name[10];
4072
4073 wifi_device_info_t info;
4074 info.wifi_devIndex = devIndex;
4075
4076 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4077
4078 nl.id = initSock80211(&nl);
4079
4080 if (nl.id < 0) {
4081 fprintf(stderr, "Error initializing netlink \n");
4082 return -1;
4083 }
4084
4085 struct nl_msg* msg = nlmsg_alloc();
4086
4087 if (!msg) {
4088 fprintf(stderr, "Failed to allocate netlink message.\n");
4089 nlfree(&nl);
4090 return -2;
4091 }
4092
4093 genlmsg_put(msg,
4094 NL_AUTO_PORT,
4095 NL_AUTO_SEQ,
4096 nl.id,
4097 0,
4098 NLM_F_DUMP,
4099 NL80211_CMD_GET_STATION,
4100 0);
4101
4102 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4103 nl_send_auto(nl.socket, msg);
4104 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4105 nl_recvmsgs(nl.socket, nl.cb);
4106 nlmsg_free(msg);
4107 nlfree(&nl);
4108
4109 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4110 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4111 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4112 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4113 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4114 return RETURN_OK;
4115#else
4116 //iw utility to retrieve station information
4117#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4118#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4119#define MACFILE "/tmp/wifi_AssoMac.txt"
4120#define TXRATEFILE "/tmp/wifi_txrate.txt"
4121#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4122 FILE *file = NULL;
4123 char if_name[10] = {'\0'};
4124 char pipeCmd[256] = {'\0'};
4125 char line[256];
4126 int count,device = 0;
4127
4128 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4129
4130 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4131 file = popen(pipeCmd, "r");
4132
4133 if(file == NULL)
4134 return RETURN_ERR; //popen failed
4135
4136 fgets(line, sizeof line, file);
4137 device = atoi(line);
4138 pclose(file);
4139
4140 if(device == 0)
4141 return RETURN_ERR; //No devices are connected
4142
4143 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4144 system(pipeCmd);
4145
4146 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4147
4148 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4149
4150 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4151
4152 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4153
4154 //devIndex starts from 1, ++count
4155 if((file = fopen(SIGNALFILE, "r")) != NULL )
4156 {
4157 for(count =0;fgets(line, sizeof line, file) != NULL;)
4158 {
4159 if (++count == devIndex)
4160 {
4161 output_struct->wifi_devSignalStrength = atoi(line);
4162 break;
4163 }
4164 }
4165 fclose(file);
4166 }
4167 else
4168 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4169
4170 if((file = fopen(MACFILE, "r")) != NULL )
4171 {
4172 for(count =0;fgets(line, sizeof line, file) != NULL;)
4173 {
4174 if (++count == devIndex)
4175 {
4176 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]);
4177 break;
4178 }
4179 }
4180 fclose(file);
4181 }
4182 else
4183 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4184
4185 if((file = fopen(TXRATEFILE, "r")) != NULL )
4186 {
4187 for(count =0;fgets(line, sizeof line, file) != NULL;)
4188 {
4189 if (++count == devIndex)
4190 {
4191 output_struct->wifi_devTxRate = atoi(line);
4192 break;
4193 }
4194 }
4195 fclose(file);
4196 }
4197 else
4198 fprintf(stderr,"fopen wifi_txrate.txt failed");
4199
4200 if((file = fopen(RXRATEFILE, "r")) != NULL)
4201 {
4202 for(count =0;fgets(line, sizeof line, file) != NULL;)
4203 {
4204 if (++count == devIndex)
4205 {
4206 output_struct->wifi_devRxRate = atoi(line);
4207 break;
4208 }
4209 }
4210 fclose(file);
4211 }
4212 else
4213 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4214
4215 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4216
4217 return RETURN_OK;
4218#endif
4219}
4220
4221INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4222{
4223 if (NULL == device)
4224 return RETURN_ERR;
4225 return RETURN_OK;
4226}
4227//<<
4228
4229
4230//--------------wifi_ap_hal-----------------------------
4231//enables CTS protection for the radio used by this AP
4232INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4233{
4234 //save config and Apply instantly
4235 return RETURN_ERR;
4236}
4237
4238// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4239INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4240{
developer463d39a2022-09-13 15:32:51 +08004241 char config_file[64] = {'\0'};
4242 char buf[64] = {'\0'};
4243 struct params list;
4244
4245 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4246 list.name = "ht_coex";
4247 snprintf(buf, sizeof(buf), "%d", enable);
4248 list.value = buf;
4249
4250 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4251 wifi_hostapdWrite(config_file, &list, 1);
4252 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4253
4254 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4255
4256 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004257}
4258
4259//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4260INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4261{
developerea4bcce2022-09-13 15:26:13 +08004262 char config_file[MAX_BUF_SIZE] = {'\0'};
4263 char buf[MAX_BUF_SIZE] = {'\0'};
4264 struct params list;
4265
4266 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4267 if (threshold < 256 || threshold > 2346 )
4268 return RETURN_ERR;
4269 list.name = "fragm_threshold";
4270 snprintf(buf, sizeof(buf), "%d", threshold);
4271 list.value = buf;
4272
4273 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4274 wifi_hostapdWrite(config_file, &list, 1);
4275 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004276
developerea4bcce2022-09-13 15:26:13 +08004277 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004278
4279 return RETURN_OK;
4280}
4281
4282// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4283INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4284{
developer51a927d2022-09-13 15:42:22 +08004285 char config_file[64] = {'\0'};
4286 char cmd[128] = {'\0'};
4287 char buf[64] = {'\0'};
4288 char stbc_config[16] = {'\0'};
4289 wifi_band band;
4290 int iterator = 0;
4291 BOOL current_stbc = FALSE;
4292
4293 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4294
4295 band = wifi_index_to_band(radioIndex);
4296 if (band == band_invalid)
4297 return RETURN_ERR;
4298
4299 if (band == band_2_4)
4300 iterator = 1;
4301 else if (band == band_5)
4302 iterator = 2;
4303 else
4304 return RETURN_OK;
4305
4306 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4307
4308 // set ht and vht config
4309 for (int i = 0; i < iterator; i++) {
4310 memset(stbc_config, 0, sizeof(stbc_config));
4311 memset(cmd, 0, sizeof(cmd));
4312 memset(buf, 0, sizeof(buf));
4313 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4314 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4315 _syscmd(cmd, buf, sizeof(buf));
4316 if (strlen(buf) != 0)
4317 current_stbc = TRUE;
4318 if (current_stbc == STBC_Enable)
4319 continue;
4320
4321 if (STBC_Enable == TRUE) {
4322 // Append the STBC flags in capab config
4323 memset(cmd, 0, sizeof(cmd));
4324 if (i == 0)
4325 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4326 else
4327 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4328 _syscmd(cmd, buf, sizeof(buf));
4329 } else if (STBC_Enable == FALSE) {
4330 // Remove the STBC flags and remain other flags in capab
4331 memset(cmd, 0, sizeof(cmd));
4332 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4333 _syscmd(cmd, buf, sizeof(buf));
4334 memset(cmd, 0, sizeof(cmd));
4335 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4336 _syscmd(cmd, buf, sizeof(buf));
4337 }
4338 }
4339
4340 wifi_reloadAp(radioIndex);
4341
4342 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4343 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004344}
4345
4346// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4347INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4348{
4349 return RETURN_ERR;
4350}
4351
4352// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4353INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4354{
4355 //Apply instantly
4356 return RETURN_ERR;
4357}
4358
4359//P2 // outputs the number of Tx streams
4360INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4361{
4362 return RETURN_ERR;
4363}
4364
4365//P2 // sets the number of Tx streams to an enviornment variable
4366INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4367{
4368 //save to wifi config, wait for wifi reset or wifi_pushTxChainMask to apply
4369 return RETURN_ERR;
4370}
4371
4372//P2 // outputs the number of Rx streams
4373INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4374{
4375 if (NULL == output_int)
4376 return RETURN_ERR;
4377 *output_int = 1;
4378 return RETURN_OK;
4379}
4380
4381//P2 // sets the number of Rx streams to an enviornment variable
4382INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4383{
4384 //save to wifi config, wait for wifi reset or wifi_pushRxChainMask to apply
4385 return RETURN_ERR;
4386}
4387
4388//Get radio RDG enable setting
4389INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4390{
4391 if (NULL == output_bool)
4392 return RETURN_ERR;
4393 *output_bool = TRUE;
4394 return RETURN_OK;
4395}
4396
4397//Get radio RDG enable setting
4398INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4399{
4400 if (NULL == output_bool)
4401 return RETURN_ERR;
4402 *output_bool = TRUE;
4403 return RETURN_OK;
4404}
4405
4406//Set radio RDG enable setting
4407INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4408{
4409 return RETURN_ERR;
4410}
4411
4412//Get radio ADDBA enable setting
4413INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4414{
4415 if (NULL == output_bool)
4416 return RETURN_ERR;
4417 *output_bool = TRUE;
4418 return RETURN_OK;
4419}
4420
4421//Set radio ADDBA enable setting
4422INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4423{
4424 return RETURN_ERR;
4425}
4426
4427//Get radio auto block ack enable setting
4428INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4429{
4430 if (NULL == output_bool)
4431 return RETURN_ERR;
4432 *output_bool = TRUE;
4433 return RETURN_OK;
4434}
4435
4436//Set radio auto block ack enable setting
4437INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4438{
4439 return RETURN_ERR;
4440}
4441
4442//Get radio 11n pure mode enable support
4443INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4444{
4445 if (NULL == output_bool)
4446 return RETURN_ERR;
4447 *output_bool = TRUE;
4448 return RETURN_OK;
4449}
4450
4451//Get radio 11n pure mode enable setting
4452INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4453{
4454 if (NULL == output_bool)
4455 return RETURN_ERR;
4456 *output_bool = TRUE;
4457 return RETURN_OK;
4458}
4459
4460//Set radio 11n pure mode enable setting
4461INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4462{
4463 return RETURN_ERR;
4464}
4465
4466//Get radio IGMP snooping enable setting
4467INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4468{
developer81bf2ed2022-09-13 15:31:14 +08004469 char cmd[128]={0};
4470 char buf[4]={0};
4471 bool bridge = FALSE, mac80211 = FALSE;
4472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4473
4474 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004475 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004476
4477 *output_bool = FALSE;
4478
4479 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4480 _syscmd(cmd, buf, sizeof(buf));
4481 if (strncmp(buf, "1", 1) == 0)
4482 bridge = TRUE;
4483
4484 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4485 _syscmd(cmd, buf, sizeof(buf));
4486 if (strncmp(buf, "1", 1) == 0)
4487 mac80211 = TRUE;
4488
4489 if (bridge && mac80211)
4490 *output_bool = TRUE;
4491
4492 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004493 return RETURN_OK;
4494}
4495
4496//Set radio IGMP snooping enable setting
4497INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4498{
developer81bf2ed2022-09-13 15:31:14 +08004499 char cmd[128]={0};
4500 char buf[4]={0};
4501
4502 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4503
4504 // bridge
4505 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4506 _syscmd(cmd, buf, sizeof(buf));
4507
4508 // mac80211
4509 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4510 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4511 _syscmd(cmd, buf, sizeof(buf));
4512 }
4513 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4514 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004515}
4516
4517//Get the Reset count of radio
4518INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4519{
4520 if (NULL == output_int)
4521 return RETURN_ERR;
4522 *output_int = (radioIndex==0)? 1: 3;
4523
4524 return RETURN_OK;
4525}
4526
4527
4528//---------------------------------------------------------------------------------------------------
4529//
4530// Additional Wifi AP level APIs used for Access Point devices
4531//
4532//---------------------------------------------------------------------------------------------------
4533
4534// creates a new ap and pushes these parameters to the hardware
4535INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4536{
4537 char buf[1024];
4538 char cmd[128];
4539
4540 if (NULL == essid)
4541 return RETURN_ERR;
4542
4543 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4544 _syscmd(cmd, buf, sizeof(buf));
4545
4546 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4547 _syscmd(cmd, buf, sizeof(buf));
4548
4549 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4550
4551 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4552 _syscmd(cmd, buf, sizeof(buf));
4553
4554 return RETURN_OK;
4555}
4556
4557// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4558INT wifi_deleteAp(INT apIndex)
4559{
4560 char buf[1024];
4561 char cmd[128];
4562
4563 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4564 _syscmd(cmd, buf, sizeof(buf));
4565
4566 wifi_removeApSecVaribles(apIndex);
4567
4568 return RETURN_OK;
4569}
4570
4571// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4572INT wifi_getApName(INT apIndex, CHAR *output_string)
4573{
4574 if(NULL == output_string)
4575 return RETURN_ERR;
4576
4577 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4578 return RETURN_OK;
4579}
4580
4581// Outputs the index number in that corresponds to the SSID string
4582INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4583{
4584 CHAR *pos = NULL;
4585
4586 *output_int = -1;
4587 pos = strstr(inputSsidString, AP_PREFIX);
4588 if(pos)
4589 {
4590 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4591 return RETURN_OK;
4592 }
4593 return RETURN_ERR;
4594}
4595
4596INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4597{
4598 return wifi_getIndexFromName(inputSsidString, output_int);
4599}
4600
4601// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4602INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4603{
4604 char buf[MAX_BUF_SIZE] = {0};
4605 char cmd[MAX_CMD_SIZE] = {0};
4606 char config_file[MAX_BUF_SIZE] = {0};
4607
4608 if(NULL == output_string)
4609 return RETURN_ERR;
4610
4611 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4612 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4613 if((strcmp(buf,"3")==0))
4614 snprintf(output_string, 32, "WPAand11i");
4615 else if((strcmp(buf,"2")==0))
4616 snprintf(output_string, 32, "11i");
4617 else if((strcmp(buf,"1")==0))
4618 snprintf(output_string, 32, "WPA");
4619 else
4620 snprintf(output_string, 32, "None");
4621
4622 return RETURN_OK;
4623}
4624
4625// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4626INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4627{
4628 char config_file[MAX_BUF_SIZE] = {0};
4629 struct params list;
4630
4631 if (NULL == beaconTypeString)
4632 return RETURN_ERR;
4633 list.name = "wpa";
4634 list.value = "0";
4635
4636 if((strcmp(beaconTypeString,"WPAand11i")==0))
4637 list.value="3";
4638 else if((strcmp(beaconTypeString,"11i")==0))
4639 list.value="2";
4640 else if((strcmp(beaconTypeString,"WPA")==0))
4641 list.value="1";
4642
4643 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4644 wifi_hostapdWrite(config_file, &list, 1);
4645 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4646 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4647 return RETURN_OK;
4648}
4649
4650// sets the beacon interval on the hardware for this AP
4651INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4652{
developer5f222492022-09-13 15:21:52 +08004653 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4654 struct params params={'\0'};
4655 char buf[MAX_BUF_SIZE] = {'\0'};
4656 char config_file[MAX_BUF_SIZE] = {'\0'};
4657
4658 params.name = "beacon_int";
4659 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4660 params.value = buf;
4661
4662 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4663 wifi_hostapdWrite(config_file, &params, 1);
4664
4665 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4666 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4667 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004668}
4669
4670INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4671{
4672 //save config and apply instantly
4673 return RETURN_ERR;
4674}
4675
4676// Get the packet size threshold supported.
4677INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4678{
4679 //save config and apply instantly
4680 if (NULL == output_bool)
4681 return RETURN_ERR;
4682 *output_bool = FALSE;
4683 return RETURN_OK;
4684}
4685
4686// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4687INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4688{
4689 char cmd[128];
4690 char buf[512];
4691
4692 if (threshold > 0)
4693 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4694 else
4695 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4696 _syscmd(cmd, buf, sizeof(buf));
4697
4698 return RETURN_OK;
4699}
4700
4701// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4702INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4703{
4704 if (NULL == output_string)
4705 return RETURN_ERR;
4706 snprintf(output_string, 32, "TKIPandAESEncryption");
4707 return RETURN_OK;
4708
4709}
4710
4711// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4712INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4713{
4714 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4715 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4716
4717 if(NULL == output_string)
4718 return RETURN_ERR;
4719
4720 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4721 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4722
4723 if(strcmp(buf,"0")==0)
4724 {
4725 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4726 snprintf(output_string, 32, "None");
4727 return RETURN_OK;
4728 }
4729 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4730 param_name = "rsn_pairwise";
4731 else if((strcmp(buf,"1")==0))
4732 param_name = "wpa_pairwise";
4733 else
4734 return RETURN_ERR;
4735 memset(output_string,'\0',32);
4736 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4737 wifi_hostapdRead(config_file,param_name,output_string,32);
4738 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4739
4740 if(strcmp(output_string,"TKIP") == 0)
4741 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4742 else if(strcmp(output_string,"CCMP") == 0)
4743 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4744 else if(strcmp(output_string,"TKIP CCMP") == 0)
4745 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4746
4747 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4748 return RETURN_OK;
4749}
4750
4751// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4752INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4753{
4754 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4755 struct params params={'\0'};
4756 char output_string[32];
4757 char config_file[MAX_BUF_SIZE] = {0};
4758
4759 memset(output_string,'\0',32);
4760 wifi_getApWpaEncryptionMode(apIndex,output_string);
4761
4762 if(strcmp(encMode, "TKIPEncryption") == 0)
4763 params.value = "TKIP";
4764 else if(strcmp(encMode,"AESEncryption") == 0)
4765 params.value = "CCMP";
4766 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4767 params.value = "TKIP CCMP";
4768
4769 if((strcmp(output_string,"WPAand11i")==0))
4770 {
4771 params.name = "wpa_pairwise";
4772 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4773 wifi_hostapdWrite(config_file, &params, 1);
4774 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4775
4776 params.name,"rsn_pairwise";
4777 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4778 wifi_hostapdWrite(config_file, &params, 1);
4779 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4780
4781 return RETURN_OK;
4782 }
4783 else if((strcmp(output_string,"11i")==0))
4784 {
4785 params.name = "rsn_pairwise";
4786 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4787 wifi_hostapdWrite(config_file, &params, 1);
4788 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4789 return RETURN_OK;
4790 }
4791 else if((strcmp(output_string,"WPA")==0))
4792 {
4793 params.name = "wpa_pairwise";
4794 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4795 wifi_hostapdWrite(config_file, &params, 1);
4796 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4797 return RETURN_OK;
4798 }
4799
4800 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4801 return RETURN_OK;
4802}
4803
4804// deletes internal security varable settings for this ap
4805INT wifi_removeApSecVaribles(INT apIndex)
4806{
4807 //TODO: remove the entry in hostapd config file
4808 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4809 //_syscmd(cmd, buf, sizeof(buf));
4810
4811 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4812 //_syscmd(cmd, buf, sizeof(buf));
4813 return RETURN_ERR;
4814}
4815
4816// changes the hardware settings to disable encryption on this ap
4817INT wifi_disableApEncryption(INT apIndex)
4818{
4819 //Apply instantly
4820 return RETURN_ERR;
4821}
4822
4823// set the authorization mode on this ap
4824// mode mapping as: 1: open, 2: shared, 4:auto
4825INT wifi_setApAuthMode(INT apIndex, INT mode)
4826{
developeraf95c502022-09-13 16:18:22 +08004827 struct params params={0};
4828 char config_file[64] = {0};
4829 int ret;
4830
4831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4832
4833 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
4834 params.name = "auth_algs";
4835
4836 if (mode & 1 && mode & 2)
4837 params.value = "3";
4838 else if (mode & 2)
4839 params.value = "2";
4840 else if (mode & 1)
4841 params.value = "1";
4842 else
4843 params.value = "0";
4844
4845 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4846 wifi_hostapdWrite(config_file, &params, 1);
4847 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4849
4850 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004851}
4852
4853// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4854INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4855{
4856 //save to wifi config, and wait for wifi restart to apply
4857 struct params params={'\0'};
4858 char config_file[MAX_BUF_SIZE] = {0};
4859 int ret;
4860
4861 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4862 if(authMode == NULL)
4863 return RETURN_ERR;
4864
4865 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
4866 params.name = "wpa_key_mgmt";
4867
4868 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
4869 params.value = "WPA-PSK";
4870 else if(strcmp(authMode,"EAPAuthentication") == 0)
4871 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08004872 else if (strcmp(authMode, "SAEAuthentication") == 0)
4873 params.value = "SAE";
4874 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
4875 params.value = "WPA-EAP-SUITE-B-192";
developer06a01d92022-09-07 16:32:39 +08004876 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
4877 return RETURN_OK; //This is taken careof in beaconType
4878
4879 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4880 ret=wifi_hostapdWrite(config_file,&params,1);
4881 if(!ret)
4882 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
4883 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4884
4885 return ret;
4886}
4887
4888// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4889INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4890{
4891 //save to wifi config, and wait for wifi restart to apply
4892 char BeaconType[50] = {0};
4893 char config_file[MAX_BUF_SIZE] = {0};
4894
4895 *authMode = 0;
4896 wifi_getApBeaconType(apIndex,BeaconType);
4897 printf("%s____%s \n",__FUNCTION__,BeaconType);
4898
4899 if(strcmp(BeaconType,"None") == 0)
4900 strcpy(authMode,"None");
4901 else
4902 {
4903 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4904 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
4905 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
4906 if(strcmp(authMode,"WPA-PSK") == 0)
4907 strcpy(authMode,"SharedAuthentication");
4908 else if(strcmp(authMode,"WPA-EAP") == 0)
4909 strcpy(authMode,"EAPAuthentication");
4910 }
4911
4912 return RETURN_OK;
4913}
4914
4915// Outputs the number of stations associated per AP
4916INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
4917{
4918 char cmd[128]={0};
4919 char buf[128]={0};
4920 BOOL status = false;
4921
4922 if(apIndex > MAX_APS)
4923 return RETURN_ERR;
4924
4925 wifi_getApEnable(apIndex,&status);
4926 if (!status)
4927 return RETURN_OK;
4928
4929 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
4930 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
4931 _syscmd(cmd, buf, sizeof(buf));
4932 sscanf(buf,"%lu", output_ulong);
4933
4934 return RETURN_OK;
4935}
4936
4937// manually removes any active wi-fi association with the device specified on this ap
4938INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
4939{
4940 char buf[126]={'\0'};
4941
4942 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
4943 system(buf);
4944
4945 return RETURN_OK;
4946}
4947
4948// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
4949INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
4950{
4951 if(NULL == output_int)
4952 return RETURN_ERR;
4953 *output_int = apIndex%2;
4954 return RETURN_OK;
4955}
4956
4957// sets the radio index for the specific ap
4958INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
4959{
4960 //set to config only and wait for wifi reset to apply settings
4961 return RETURN_ERR;
4962}
4963
4964// Get the ACL MAC list per AP
4965INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4966{
4967 char cmd[MAX_CMD_SIZE]={'\0'};
4968 int ret = 0;
4969
4970 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4971 ret = _syscmd(cmd,macArray,buf_size);
4972 if (ret != 0)
4973 return RETURN_ERR;
4974
4975 return RETURN_OK;
4976}
4977
developere6aafda2022-09-13 14:59:28 +08004978INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4979{
4980 char cmd[MAX_CMD_SIZE]={'\0'};
4981 int ret = 0;
4982
4983 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4984 ret = _syscmd(cmd,macArray,buf_size);
4985 if (ret != 0)
4986 return RETURN_ERR;
4987
4988 return RETURN_OK;
4989}
4990
4991
developer06a01d92022-09-07 16:32:39 +08004992// Get the list of stations associated per AP
4993INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
4994{
4995 char cmd[128];
4996
4997 if(apIndex > 3) //Currently supporting apIndex upto 3
4998 return RETURN_ERR;
4999 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5000 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5001 _syscmd(cmd, macArray, buf_size);
5002
5003 return RETURN_OK;
5004}
5005
5006// adds the mac address to the filter list
5007//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5008INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5009{
5010 char cmd[MAX_CMD_SIZE]={'\0'};
5011 char buf[MAX_BUF_SIZE]={'\0'};
5012
5013#if 0
5014 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5015 if(_syscmd(cmd,buf,sizeof(buf)))
5016 return RETURN_ERR;
5017#endif
5018 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5019 if(_syscmd(cmd,buf,sizeof(buf)))
5020 return RETURN_ERR;
5021
5022 return RETURN_OK;
5023}
5024
5025// deletes the mac address from the filter list
5026//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5027INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5028{
5029 char cmd[MAX_CMD_SIZE]={'\0'};
5030 char buf[MAX_BUF_SIZE]={'\0'};
5031
5032#if 0
5033 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5034 if(_syscmd(cmd,buf,sizeof(buf)))
5035 return RETURN_ERR;
5036
5037#endif
5038 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5039 if(_syscmd(cmd,buf,sizeof(buf)))
5040 return RETURN_ERR;
5041
5042 return RETURN_OK;
5043}
5044
5045// outputs the number of devices in the filter list
5046INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5047{
developere6aafda2022-09-13 14:59:28 +08005048 char cmd[MAX_BUF_SIZE]={0};
5049 char buf[MAX_CMD_SIZE]={0};
5050
5051 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5052 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005053 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005054
5055 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5056 _syscmd(cmd, buf, sizeof(buf));
5057
5058 *output_uint = atoi(buf);
5059
5060 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5061 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005062}
5063
5064INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5065{
5066 char cmd[128]={'\0'};
5067 char buf[128]={'\0'};
5068
5069 if(strcmp(action,"DENY")==0)
5070 {
5071 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5072 system(buf);
5073 return RETURN_OK;
5074 }
5075
5076 if(strcmp(action,"ALLOW")==0)
5077 {
5078 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5079 system(buf);
5080 return RETURN_OK;
5081 }
5082
5083 return RETURN_ERR;
5084
5085}
5086
5087// enable kick for devices on acl black list
5088INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5089{
5090 char aclArray[512] = {0}, *acl = NULL;
5091 char assocArray[512] = {0}, *asso = NULL;
5092
developere6aafda2022-09-13 14:59:28 +08005093 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005094 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5095
5096 // if there are no devices connected there is nothing to do
5097 if (strlen(assocArray) < 17)
5098 return RETURN_OK;
5099
5100 if (enable == TRUE)
5101 {
5102 //kick off the MAC which is in ACL array (deny list)
5103 acl = strtok(aclArray, "\r\n");
5104 while (acl != NULL) {
5105 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5106 wifi_kickApAssociatedDevice(apIndex, acl);
5107
5108 acl = strtok(NULL, "\r\n");
5109 }
developere6aafda2022-09-13 14:59:28 +08005110 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005111 }
5112 else
5113 {
developere6aafda2022-09-13 14:59:28 +08005114 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005115 }
5116
5117#if 0
5118 //TODO: need to revisit below implementation
5119 char aclArray[512]={0}, *acl=NULL;
5120 char assocArray[512]={0}, *asso=NULL;
5121 char buf[256]={'\0'};
5122 char action[10]={'\0'};
5123 FILE *fr=NULL;
5124 char interface[10]={'\0'};
5125 char config_file[MAX_BUF_SIZE] = {0};
5126
5127 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5128 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5129 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5130 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5131
5132 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5133 system(buf);
5134 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5135 system(buf);
5136 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5137 system(buf);
5138 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5139 system(buf);
5140 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5141 system(buf);
5142
5143 if ( enable == TRUE )
5144 {
5145 int device_count=0;
5146 strcpy(action,"DENY");
5147 //kick off the MAC which is in ACL array (deny list)
5148 acl = strtok (aclArray,",");
5149 while (acl != NULL) {
5150 if(strlen(acl)>=17)
5151 {
5152 apply_rules(apIndex, acl,action,interface);
5153 device_count++;
5154 //Register mac to be blocked ,in syscfg.db persistent storage
5155 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5156 system(buf);
5157 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5158 system(buf);
5159 system("syscfg commit");
5160
5161 wifi_kickApAssociatedDevice(apIndex, acl);
5162 }
5163 acl = strtok (NULL, ",");
5164 }
5165 }
5166 else
5167 {
5168 int device_count=0;
5169 char cmdmac[20]={'\0'};
5170 strcpy(action,"ALLOW");
5171 //kick off the MAC which is not in ACL array (allow list)
5172 acl = strtok (aclArray,",");
5173 while (acl != NULL) {
5174 if(strlen(acl)>=17)
5175 {
5176 apply_rules(apIndex, acl,action,interface);
5177 device_count++;
5178 //Register mac to be Allowed ,in syscfg.db persistent storage
5179 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5180 system(buf);
5181 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5182 system(buf);
5183 sprintf(cmdmac,"%s",acl);
5184 }
5185 acl = strtok (NULL, ",");
5186 }
5187 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5188 system(buf);
5189
5190 //Disconnect the mac which is not in ACL
5191 asso = strtok (assocArray,",");
5192 while (asso != NULL) {
5193 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5194 wifi_kickApAssociatedDevice(apIndex, asso);
5195 asso = strtok (NULL, ",");
5196 }
5197 }
5198#endif
5199 return RETURN_OK;
5200}
5201
5202INT wifi_setPreferPrivateConnection(BOOL enable)
5203{
5204 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5205 char buf[1024] = {0};
5206
5207 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5208 if(enable == TRUE)
5209 {
5210 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5211 sprintf(buf,"ifconfig %s down" ,interface_name);
5212 system(buf);
5213 memset(buf,0,sizeof(buf));
5214 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5215 sprintf(buf,"ifconfig %s down" ,interface_name);
5216 system(buf);
5217 }
5218 else
5219 {
5220 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5221 if(strcmp(ssid_cur_value,"1") == 0)
5222 wifi_RestartPrivateWifi_5G();
5223 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5224 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5225 if(strcmp(ssid_cur_value,"1") == 0)
5226 wifi_RestartHostapd_2G();
5227 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5228 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5229 if(strcmp(ssid_cur_value,"1") == 0)
5230 wifi_RestartHostapd_5G();
5231 }
5232 return RETURN_OK;
5233}
5234
5235// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5236INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5237{
5238 int items = 1;
5239 struct params list[2];
5240 char buf[MAX_BUF_SIZE] = {0};
5241 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005242 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005243
5244 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005245
developer10adcc12022-09-13 14:39:17 +08005246 if (filterMode == 0) {
5247 sprintf(buf, "%d", 0);
5248 list[0].value = buf;
5249
5250 char cmd[128], rtn[128];
5251 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5252 _syscmd(cmd, rtn, sizeof(rtn));
5253 memset(cmd,0,sizeof(cmd));
5254 // Delete deny_mac_file in hostapd configuration
5255 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5256 _syscmd(cmd, rtn, sizeof(rtn));
5257 }
5258 else if (filterMode == 1) {
5259 sprintf(buf, "%d", filterMode);
5260 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005261 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5262 list[1].name = "accept_mac_file";
5263 list[1].value = acl_file;
5264 items = 2;
developer10adcc12022-09-13 14:39:17 +08005265 } else if (filterMode == 2) {
5266 //TODO: deny_mac_file
5267 sprintf(buf, "%d", 0);
5268 list[0].value = buf;
5269 list[1].name = "deny_mac_file";
5270 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5271 list[1].value = deny_file;
5272 items = 2;
5273 } else {
5274 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005275 }
developer10adcc12022-09-13 14:39:17 +08005276
developer06a01d92022-09-07 16:32:39 +08005277 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5278 wifi_hostapdWrite(config_file, list, items);
5279
5280 return RETURN_OK;
5281
5282#if 0
5283 if(apIndex==0 || apIndex==1)
5284 {
5285 //set the filtermode
5286 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5287 system(buf);
5288 system("syscfg commit");
5289
5290 if(filterMode==0)
5291 {
5292 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5293 system(buf);
5294 return RETURN_OK;
5295 }
5296 }
5297 return RETURN_OK;
5298#endif
5299}
5300
5301// 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.
5302INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5303{
5304 return RETURN_ERR;
5305}
5306
5307// gets the vlan ID for this ap from an internal enviornment variable
5308INT wifi_getApVlanID(INT apIndex, INT *output_int)
5309{
5310 if(apIndex=0)
5311 {
5312 *output_int=100;
5313 return RETURN_OK;
5314 }
5315
5316 return RETURN_ERR;
5317}
5318
5319// sets the vlan ID for this ap to an internal enviornment variable
5320INT wifi_setApVlanID(INT apIndex, INT vlanId)
5321{
5322 //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)
5323 return RETURN_ERR;
5324}
5325
5326// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5327INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5328{
5329 snprintf(bridgeName, 32, "brlan0");
5330 snprintf(IP, 32, "10.0.0.1");
5331 snprintf(subnet, 32, "255.255.255.0");
5332
5333 return RETURN_OK;
5334}
5335
5336//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5337INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5338{
5339 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5340 return RETURN_ERR;
5341}
5342
5343// reset the vlan configuration for this ap
5344INT wifi_resetApVlanCfg(INT apIndex)
5345{
5346 //TODO: remove existing vlan for this ap
5347
5348 //Reapply vlan settings
5349 wifi_pushBridgeInfo(apIndex);
5350
5351 return RETURN_ERR;
5352}
5353
5354// 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.
5355INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5356{
5357 return RETURN_ERR;
5358}
5359
5360// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5361INT wifi_startHostApd()
5362{
5363 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5364 system("systemctl start hostapd.service");
5365 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5366 return RETURN_OK;
5367 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5368}
5369
5370// stops hostapd
5371INT wifi_stopHostApd()
5372{
5373 char cmd[128] = {0};
5374 char buf[128] = {0};
5375
5376 sprintf(cmd,"systemctl stop hostapd");
5377 _syscmd(cmd, buf, sizeof(buf));
5378
5379 return RETURN_OK;
5380}
5381
5382// restart hostapd dummy function
5383INT wifi_restartHostApd()
5384{
5385 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5386 system("systemctl restart hostapd-global");
5387 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5388
5389 return RETURN_OK;
5390}
5391
5392static int align_hostapd_config(int index)
5393{
5394 ULONG lval;
5395 wifi_getRadioChannel(index%2, &lval);
5396 wifi_setRadioChannel(index%2, lval);
5397}
5398
5399// sets the AP enable status variable for the specified ap.
5400INT wifi_setApEnable(INT apIndex, BOOL enable)
5401{
5402 char config_file[MAX_BUF_SIZE] = {0};
5403 char cmd[MAX_CMD_SIZE] = {0};
5404 char buf[MAX_BUF_SIZE] = {0};
5405 BOOL status;
5406
5407 wifi_getApEnable(apIndex,&status);
5408 if (enable == status)
5409 return RETURN_OK;
5410
5411 if (enable == TRUE) {
5412 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5413 align_hostapd_config(apIndex);
5414 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5415 //Hostapd will bring up this interface
5416 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5417 _syscmd(cmd, buf, sizeof(buf));
5418 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5419 _syscmd(cmd, buf, sizeof(buf));
5420 }
5421 else {
5422 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5423 _syscmd(cmd, buf, sizeof(buf));
5424 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5425 _syscmd(cmd, buf, sizeof(buf));
5426 }
5427 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5428 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5429 _syscmd(cmd, buf, sizeof(buf));
5430 //Wait for wifi up/down to apply
5431 return RETURN_OK;
5432}
5433
5434// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5435INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5436{
5437 char cmd[MAX_CMD_SIZE] = {'\0'};
5438 char buf[MAX_BUF_SIZE] = {'\0'};
5439
5440 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5441 return RETURN_ERR;
5442
5443 *output_bool = 0;
5444
5445 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5446 {
developer70490032022-09-13 15:45:20 +08005447 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005448 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5449 }
5450
5451 return RETURN_OK;
5452}
5453
5454// Outputs the AP "Enabled" "Disabled" status from driver
5455INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5456{
5457 char cmd[128] = {0};
5458 char buf[128] = {0};
5459 BOOL output_bool;
5460
5461 if ( NULL == output_string)
5462 return RETURN_ERR;
5463 wifi_getApEnable(apIndex,&output_bool);
5464
5465 if(output_bool == 1)
5466 snprintf(output_string, 32, "Up");
5467 else
5468 snprintf(output_string, 32, "Disable");
5469
5470 return RETURN_OK;
5471}
5472
5473//Indicates whether or not beacons include the SSID name.
5474// outputs a 1 if SSID on the AP is enabled, else outputs 0
5475INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5476{
5477 //get the running status
5478 char config_file[MAX_BUF_SIZE] = {0};
5479 char buf[16] = {0};
5480
5481 if (!output)
5482 return RETURN_ERR;
5483
5484 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5485 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5486 *output = (strncmp("0",buf,1) == 0);
5487
5488 return RETURN_OK;
5489}
5490
5491// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5492INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5493{
5494 //store the config, apply instantly
5495 char config_file[MAX_BUF_SIZE] = {0};
5496 struct params list;
5497
5498 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5499 list.name = "ignore_broadcast_ssid";
5500 list.value = enable?"0":"1";
5501
5502 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5503 wifi_hostapdWrite(config_file, &list, 1);
5504 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5505 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005506 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5508
5509 return RETURN_OK;
5510}
5511
5512//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5513INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5514{
5515 //get the running status
5516 if(!output_uint)
5517 return RETURN_ERR;
5518 *output_uint=16;
5519 return RETURN_OK;
5520}
5521
5522INT wifi_setApRetryLimit(INT apIndex, UINT number)
5523{
5524 //apply instantly
5525 return RETURN_ERR;
5526}
5527
5528//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5529INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5530{
5531 if(!output)
5532 return RETURN_ERR;
5533 *output=TRUE;
5534 return RETURN_OK;
5535}
5536
5537//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5538INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5539{
5540 //get the running status from driver
5541 if(!output)
5542 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005543
5544 char config_file[MAX_BUF_SIZE] = {0};
5545 char buf[16] = {0};
5546
5547 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5548 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
5549 if (strncmp("1",buf,1) == 0)
5550 *output = TRUE;
5551 else
5552 *output = FALSE;
5553
developer06a01d92022-09-07 16:32:39 +08005554 return RETURN_OK;
5555}
5556
5557//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5558INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5559{
5560 //get the running status from driver
5561 if(!output)
5562 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005563
5564 char config_file[MAX_BUF_SIZE] = {0};
5565 char buf[16] = {0};
5566
5567 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5568 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5569 if (strncmp("1",buf,1) == 0)
5570 *output = TRUE;
5571 else
5572 *output = FALSE;
5573
developer06a01d92022-09-07 16:32:39 +08005574 return RETURN_OK;
5575}
5576
5577// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5578INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5579{
5580 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005581 char config_file[MAX_BUF_SIZE] = {0};
5582 struct params list;
5583
5584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5585 list.name = "wmm_enabled";
5586 list.value = enable?"1":"0";
5587
5588 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5589 wifi_hostapdWrite(config_file, &list, 1);
5590 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5591 wifi_reloadAp(apIndex);
5592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5593
5594 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005595}
5596
5597//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.
5598INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5599{
5600 //get the running status from driver
5601 if(!output)
5602 return RETURN_ERR;
5603 *output=TRUE;
5604 return RETURN_OK;
5605}
5606
5607// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5608INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5609{
5610 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005611 char config_file[MAX_BUF_SIZE] = {0};
5612 struct params list;
5613
5614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5615 list.name = "uapsd_advertisement_enabled";
5616 list.value = enable?"1":"0";
5617
5618 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5619 wifi_hostapdWrite(config_file, &list, 1);
5620 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5621 wifi_reloadAp(apIndex);
5622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5623
5624 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005625}
5626
5627// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
5628INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5629{
5630 //save config and apply instantly.
5631 return RETURN_ERR;
5632}
5633
5634//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.
5635INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5636{
5637 //get the running status from driver
5638 if(!output_uint)
5639 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005640
5641 char output[16]={'\0'};
5642 char config_file[MAX_BUF_SIZE] = {0};
5643
5644 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5645 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5646 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5647 else {
5648 int device_num = atoi(output);
5649 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5650 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5651 return RETURN_ERR;
5652 }
5653 else {
5654 *output_uint = device_num;
5655 }
5656 }
5657
developer06a01d92022-09-07 16:32:39 +08005658 return RETURN_OK;
5659}
5660
5661INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5662{
5663 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005664 char str[MAX_BUF_SIZE]={'\0'};
5665 char cmd[MAX_CMD_SIZE]={'\0'};
5666 struct params params;
5667 char config_file[MAX_BUF_SIZE] = {0};
5668
5669 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5670 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5671 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5672 return RETURN_ERR;
5673 }
5674 sprintf(str, "%d", number);
5675 params.name = "max_num_sta";
5676 params.value = str;
5677
5678 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5679 int ret = wifi_hostapdWrite(config_file, &params, 1);
5680 if (ret) {
5681 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5682 ,__func__, ret);
5683 }
5684
5685 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5686 if (ret) {
5687 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5688 ,__func__, ret);
5689 }
5690 wifi_reloadAp(apIndex);
5691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5692
5693 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005694}
5695
5696//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.
5697INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5698{
5699 //get the current threshold
5700 if(!output_uint)
5701 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005702 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5703 if (*output_uint == 0)
5704 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08005705 return RETURN_OK;
5706}
5707
5708INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
5709{
5710 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08005711 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
5712 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005713 return RETURN_ERR;
5714}
5715
5716//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.
5717INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
5718{
5719 if(!output_uint)
5720 return RETURN_ERR;
5721 *output_uint = 3;
5722 return RETURN_OK;
5723}
5724
5725//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
5726INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
5727{
5728 if(!output_uint)
5729 return RETURN_ERR;
5730 *output_uint = 3;
5731 return RETURN_OK;
5732}
5733
5734//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.
5735INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
5736{
5737 if(!output_in_seconds)
5738 return RETURN_ERR;
5739 *output_in_seconds = 0;
5740 return RETURN_OK;
5741}
5742
5743//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
5744INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
5745{
5746 if(!output || apIndex>=MAX_APS)
5747 return RETURN_ERR;
5748 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08005749 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08005750 return RETURN_OK;
5751}
5752
5753//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
5754INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
5755{
developer587c1b62022-09-27 15:58:59 +08005756 char config_file[128] = {0};
5757 char wpa[16] = {0};
5758 char key_mgmt[64] = {0};
5759 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005760 if (!output)
5761 return RETURN_ERR;
5762
5763 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08005764 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08005765
developer587c1b62022-09-27 15:58:59 +08005766 strcpy(output, "None");//Copying "None" to output string for default case
5767 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
5768 if (strstr(key_mgmt, "WPA-PSK")) {
5769 if (strcmp(wpa, "1"))
5770 snprintf(output, 32, "WPA-Personal");
5771 else if (strcmp(wpa, "2"))
5772 snprintf(output, 32, "WPA2-Personal");
5773 else if (strcmp(wpa, "3"))
5774 snprintf(output, 32, "WPA-WPA2-Personal");
5775
5776 } else if (strstr(key_mgmt, "WPA-EAP")) {
5777 if (strcmp(wpa, "1"))
5778 snprintf(output, 32, "WPA-Enterprise");
5779 else if (strcmp(wpa, "2"))
5780 snprintf(output, 32, "WPA2-Enterprise");
5781 else if (strcmp(wpa, "3"))
5782 snprintf(output, 32, "WPA-WPA2-Enterprise");
5783 } else if (strstr(key_mgmt, "SAE")) {
5784 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
5785 int disable = strtol(buf, NULL, 16);
5786 if (disable & 0x1)
5787 snprintf(output, 32, "WPA3-Personal");
5788 else
5789 snprintf(output, 32, "WPA3-Transition");
5790 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
5791 snprintf(output, 32, "WPA3-Enterprise");
5792 }
developer06a01d92022-09-07 16:32:39 +08005793
5794 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5795 return RETURN_OK;
5796#if 0
5797 //TODO: need to revisit below implementation
5798 char securityType[32], authMode[32];
5799 int enterpriseMode=0;
5800
5801 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5802 if(!output)
5803 return RETURN_ERR;
5804
5805 wifi_getApBeaconType(apIndex, securityType);
5806 strcpy(output,"None");//By default, copying "None" to output string
5807 if (strncmp(securityType,"None", strlen("None")) == 0)
5808 return RETURN_OK;
5809
5810 wifi_getApBasicAuthenticationMode(apIndex, authMode);
5811 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
5812
5813 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
5814 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
5815 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
5816 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
5817 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
5818 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
5819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5820
5821 return RETURN_OK;
5822#endif
5823}
5824
5825INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
5826{
5827 char securityType[32];
5828 char authMode[32];
5829
5830 //store settings and wait for wifi up to apply
5831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5832 if(!encMode)
5833 return RETURN_ERR;
5834
developer06a01d92022-09-07 16:32:39 +08005835 if (strcmp(encMode, "None")==0)
5836 {
5837 strcpy(securityType,"None");
5838 strcpy(authMode,"None");
5839 }
5840 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
5841 {
5842 strcpy(securityType,"WPAand11i");
5843 strcpy(authMode,"PSKAuthentication");
5844 }
5845 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
5846 {
5847 strcpy(securityType,"WPAand11i");
5848 strcpy(authMode,"EAPAuthentication");
5849 }
5850 else if (strcmp(encMode, "WPA-Personal")==0)
5851 {
5852 strcpy(securityType,"WPA");
5853 strcpy(authMode,"PSKAuthentication");
5854 }
5855 else if (strcmp(encMode, "WPA-Enterprise")==0)
5856 {
5857 strcpy(securityType,"WPA");
5858 strcpy(authMode,"EAPAuthentication");
5859 }
5860 else if (strcmp(encMode, "WPA2-Personal")==0)
5861 {
5862 strcpy(securityType,"11i");
5863 strcpy(authMode,"PSKAuthentication");
5864 }
5865 else if (strcmp(encMode, "WPA2-Enterprise")==0)
5866 {
5867 strcpy(securityType,"11i");
5868 strcpy(authMode,"EAPAuthentication");
5869 }
developer587c1b62022-09-27 15:58:59 +08005870 else if (strcmp(encMode, "WPA3-Personal") == 0)
5871 {
5872 strcpy(securityType,"11i");
5873 strcpy(authMode,"SAEAuthentication");
5874 }
5875 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
5876 {
5877 strcpy(securityType,"11i");
5878 strcpy(authMode,"EAP_192-bit_Authentication");
5879 }
developer06a01d92022-09-07 16:32:39 +08005880 else
5881 {
5882 strcpy(securityType,"None");
5883 strcpy(authMode,"None");
5884 }
5885 wifi_setApBeaconType(apIndex, securityType);
5886 wifi_setApBasicAuthenticationMode(apIndex, authMode);
5887 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5888
5889 return RETURN_OK;
5890}
5891
5892
5893//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
5894// output_string must be pre-allocated as 64 character string by caller
5895// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5896INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
5897{
5898 char buf[16];
5899 char config_file[MAX_BUF_SIZE] = {0};
5900
5901 if(output_string==NULL)
5902 return RETURN_ERR;
5903
5904 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5905 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5906
5907 if(strcmp(buf,"0")==0)
5908 {
5909 printf("wpa_mode is %s ......... \n",buf);
5910 return RETURN_ERR;
5911 }
5912
5913 wifi_dbg_printf("\nFunc=%s\n",__func__);
5914 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5915 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5916 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5917
5918 return RETURN_OK;
5919}
5920
5921// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
5922// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5923INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
5924{
5925 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5926 struct params params={'\0'};
5927 int ret;
5928 char config_file[MAX_BUF_SIZE] = {0};
5929
5930 if(NULL == preSharedKey)
5931 return RETURN_ERR;
5932
5933 params.name = "wpa_passphrase";
5934
5935 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
5936 {
5937 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5938 return RETURN_ERR;
5939 }
5940 params.value = preSharedKey;
5941 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5942 ret = wifi_hostapdWrite(config_file, &params, 1);
5943 if(!ret)
5944 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5945 return ret;
5946 //TODO: call hostapd_cli for dynamic_config_control
5947}
5948
5949//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
5950// outputs the passphrase, maximum 63 characters
5951INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
5952{
5953 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
5954
5955 wifi_dbg_printf("\nFunc=%s\n",__func__);
5956 if (NULL == output_string)
5957 return RETURN_ERR;
5958
5959 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5960 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5961 if(strcmp(buf,"0")==0)
5962 {
5963 printf("wpa_mode is %s ......... \n",buf);
5964 return RETURN_ERR;
5965 }
5966
5967 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5968 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5969
5970 return RETURN_OK;
5971}
5972
5973// sets the passphrase enviornment variable, max 63 characters
5974INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
5975{
5976 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5977 struct params params={'\0'};
5978 char config_file[MAX_BUF_SIZE] = {0};
5979 int ret;
5980
5981 if(NULL == passPhrase)
5982 return RETURN_ERR;
5983
5984 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
5985 {
5986 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5987 return RETURN_ERR;
5988 }
5989 params.name = "wpa_passphrase";
5990 params.value = passPhrase;
5991 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5992 ret=wifi_hostapdWrite(config_file,&params,1);
5993 if(!ret)
5994 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5995
5996 return ret;
5997}
5998
5999//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.
6000INT wifi_setApSecurityReset(INT apIndex)
6001{
6002 //apply instantly
6003 return RETURN_ERR;
6004}
6005
6006//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).
6007INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6008{
developer8f2ddd52022-09-13 15:39:24 +08006009 char config_file[64] = {0};
6010 char buf[64] = {0};
6011 char cmd[256] = {0};
6012
6013 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6014
developer06a01d92022-09-07 16:32:39 +08006015 if(!IP_output || !Port_output || !RadiusSecret_output)
6016 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006017
developer8f2ddd52022-09-13 15:39:24 +08006018 // Read the first matched config
6019 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6020 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6021 _syscmd(cmd, buf, sizeof(buf));
6022 strncpy(IP_output, buf, 64);
6023
6024 memset(buf, 0, sizeof(buf));
6025 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6026 _syscmd(cmd, buf, sizeof(buf));
6027 *Port_output = atoi(buf);
6028
6029 memset(buf, 0, sizeof(buf));
6030 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6031 _syscmd(cmd, buf, sizeof(buf));
6032 strncpy(RadiusSecret_output, buf, 64);
6033
6034 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006035 return RETURN_OK;
6036}
6037
6038INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6039{
developer8f2ddd52022-09-13 15:39:24 +08006040 char config_file[64] = {0};
6041 char port_str[8] = {0};
6042 char cmd[256] = {0};
6043 char buf[128] = {0};
6044
6045 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6046
6047 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6048
6049 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6050 _syscmd(cmd, buf, sizeof(buf));
6051 memset(cmd, 0, sizeof(cmd));
6052
6053 snprintf(port_str, sizeof(port_str), "%d", port);
6054 if (strlen(buf) == 0)
6055 // Append
6056 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6057 "auth_server_addr=%s\\n"
6058 "auth_server_port=%s\\n"
6059 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6060 else {
6061 // Delete the three lines setting after the "# radius 1" comment
6062 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6063 _syscmd(cmd, buf, sizeof(buf));
6064 memset(cmd, 0, sizeof(cmd));
6065 // Use "# radius 1" comment to find the location to insert the radius setting
6066 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6067 "# radius 1\\n"
6068 "auth_server_addr=%s\\n"
6069 "auth_server_port=%s\\n"
6070 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6071 }
6072 if(_syscmd(cmd, buf, sizeof(buf))) {
6073 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6074 return RETURN_ERR;
6075 }
6076
6077 wifi_reloadAp(apIndex);
6078 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6079 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006080}
6081
6082INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6083{
developer8f2ddd52022-09-13 15:39:24 +08006084 char config_file[64] = {0};
6085 char buf[64] = {0};
6086 char cmd[256] = {0};
6087
6088 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6089
developer06a01d92022-09-07 16:32:39 +08006090 if(!IP_output || !Port_output || !RadiusSecret_output)
6091 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006092
6093 // Read the second matched config
6094 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6095 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6096 _syscmd(cmd, buf, sizeof(buf));
6097 strncpy(IP_output, buf, 64);
6098
6099 memset(buf, 0, sizeof(buf));
6100 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6101 _syscmd(cmd, buf, sizeof(buf));
6102 *Port_output = atoi(buf);
6103
6104 memset(buf, 0, sizeof(buf));
6105 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6106 _syscmd(cmd, buf, sizeof(buf));
6107 strncpy(RadiusSecret_output, buf, 64);
6108
6109 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006110 return RETURN_OK;
6111}
6112
6113INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6114{
developer8f2ddd52022-09-13 15:39:24 +08006115 char config_file[64] = {0};
6116 char port_str[8] = {0};
6117 char cmd[256] = {0};
6118 char buf[128] = {0};
6119
6120 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6121
6122 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6123
6124 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6125 _syscmd(cmd, buf, sizeof(buf));
6126 memset(cmd, 0, sizeof(cmd));
6127
6128 snprintf(port_str, sizeof(port_str), "%d", port);
6129 if (strlen(buf) == 0)
6130 // Append
6131 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6132 "auth_server_addr=%s\\n"
6133 "auth_server_port=%s\\n"
6134 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6135 else {
6136 // Delete the three lines setting after the "# radius 2" comment
6137 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6138 _syscmd(cmd, buf, sizeof(buf));
6139 memset(cmd, 0, sizeof(cmd));
6140 // Use "# radius 2" comment to find the location to insert the radius setting
6141 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6142 "# radius 2\\n"
6143 "auth_server_addr=%s\\n"
6144 "auth_server_port=%s\\n"
6145 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6146 }
6147 if(_syscmd(cmd, buf, sizeof(buf))) {
6148 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6149 return RETURN_ERR;
6150 }
6151
6152 wifi_reloadAp(apIndex);
6153 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6154 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006155}
6156
6157//RadiusSettings
6158INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6159{
6160 if(!output)
6161 return RETURN_ERR;
6162
6163 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6164 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6165 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6166 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6167 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6168 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.
6169 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6170 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6171 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6172 //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.
6173
6174 return RETURN_OK;
6175}
6176
6177INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6178{
6179 //store the paramters, and apply instantly
6180 return RETURN_ERR;
6181}
6182
6183//Device.WiFi.AccessPoint.{i}.WPS.Enable
6184//Enables or disables WPS functionality for this access point.
6185// outputs the WPS enable state of this ap in output_bool
6186INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6187{
6188 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6189 if(!output_bool || !(apIndex==0 || apIndex==1))
6190 return RETURN_ERR;
6191 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6192 _syscmd(cmd, buf, sizeof(buf));
6193 if(strstr(buf, "configured"))
6194 *output_bool=TRUE;
6195 else
6196 *output_bool=FALSE;
6197
6198 return RETURN_OK;
6199}
6200
6201//Device.WiFi.AccessPoint.{i}.WPS.Enable
6202// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6203INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6204{
6205 char config_file[MAX_BUF_SIZE] = {0};
6206 struct params params;
6207
6208 if(!(apIndex==0 || apIndex==1))
6209 return RETURN_ERR;
6210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6211 //store the paramters, and wait for wifi up to apply
6212 params.name = "wps_state";
6213 params.value = enable ? "2":"0";
6214
6215 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6216 wifi_hostapdWrite(config_file, &params, 1);
6217 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6218 wifi_reloadAp(apIndex);
6219
6220 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6221 return RETURN_OK;
6222}
6223
6224//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
6225INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6226{
6227 if(!output)
6228 return RETURN_ERR;
6229 snprintf(output, 128, "PushButton,PIN");
6230 return RETURN_OK;
6231}
6232
6233//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6234//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.
6235// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6236INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6237{
6238 if(!output)
6239 return RETURN_ERR;
6240 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6241
6242 return RETURN_OK;
6243}
6244
6245//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6246// 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
6247INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6248{
6249 //apply instantly. No setting need to be stored.
6250 char methods[MAX_BUF_SIZE], *token, *next_token;
6251 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6252 struct params params;
6253
6254 if(!methodString || !(apIndex==0 || apIndex==1))
6255 return RETURN_ERR;
6256 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6257 //store the paramters, and wait for wifi up to apply
6258
6259 snprintf(methods, sizeof(methods), "%s", methodString);
6260 for(token=methods; *token; token=next_token)
6261 {
6262 strtok_r(token, ",", &next_token);
6263 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6264 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6265 else if(*token=='E')
6266 {
6267 if(!strcmp(methods, "Ethernet"))
6268 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6269 else if(!strcmp(methods, "ExternalNFCToken"))
6270 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6271 else
6272 printf("%s: Unknown WpsConfigMethod\n", __func__);
6273 }
6274 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6275 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6276 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6277 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6278 else if(*token=='P' )
6279 {
6280 if(!strcmp(token, "PushButton"))
6281 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6282 else if(!strcmp(token, "PIN"))
6283 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6284 else
6285 printf("%s: Unknown WpsConfigMethod\n", __func__);
6286 }
6287 else
6288 printf("%s: Unknown WpsConfigMethod\n", __func__);
6289 }
6290 params.name = "config_methods";
6291 params.value = config_methods;
6292 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6293 wifi_hostapdWrite(config_file, &params, 1);
6294 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6295 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6296
6297 return RETURN_OK;
6298}
6299
6300// outputs the pin value, ulong_pin must be allocated by the caller
6301INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6302{
6303 char buf[MAX_BUF_SIZE] = {0};
6304 char cmd[MAX_CMD_SIZE] = {0};
6305
6306 if(!output_ulong || !(apIndex==0 || apIndex==1))
6307 return RETURN_ERR;
6308 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6309 _syscmd(cmd, buf, sizeof(buf));
6310 if(strlen(buf) > 0)
6311 *output_ulong=strtoul(buf, NULL, 10);
6312
6313 return RETURN_OK;
6314}
6315
6316// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6317INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6318{
6319 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6320 char ap_pin[16] = {0};
6321 char buf[MAX_BUF_SIZE] = {0};
6322 char config_file[MAX_BUF_SIZE] = {0};
6323 ULONG prev_pin = 0;
6324 struct params params;
6325
6326 if(!(apIndex==0 || apIndex==1))
6327 return RETURN_ERR;
6328 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6329 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6330 params.name = "ap_pin";
6331 params.value = ap_pin;
6332 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6333 wifi_hostapdWrite(config_file, &params, 1);
6334 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6335 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6336
6337 return RETURN_OK;
6338}
6339
6340// Output string is either Not configured or Configured, max 32 characters
6341INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6342{
6343 char cmd[MAX_CMD_SIZE];
6344 char buf[MAX_BUF_SIZE]={0};
6345
6346 if(!output_string || !(apIndex==0 || apIndex==1))
6347 return RETURN_ERR;
6348 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6349 snprintf(output_string, 32, "Not configured");
6350 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6351 _syscmd(cmd, buf, sizeof(buf));
6352
developer348e3d92022-09-13 14:48:41 +08006353 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006354 snprintf(output_string, 32, "Configured");
6355 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6356
6357 return RETURN_OK;
6358}
6359
6360// sets the WPS pin for this AP
6361INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6362{
6363 char cmd[MAX_CMD_SIZE];
6364 char buf[MAX_BUF_SIZE]={0};
6365 BOOL enable;
6366
6367 if(!(apIndex==0 || apIndex==1))
6368 return RETURN_ERR;
6369 wifi_getApEnable(apIndex, &enable);
6370 if (!enable)
6371 return RETURN_ERR;
6372 wifi_getApWpsEnable(apIndex, &enable);
6373 if (!enable)
6374 return RETURN_ERR;
6375
6376 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6377 _syscmd(cmd, buf, sizeof(buf));
6378 if((strstr(buf, "OK"))!=NULL)
6379 return RETURN_OK;
6380
6381 return RETURN_ERR;
6382}
6383
6384// This function is called when the WPS push button has been pressed for this AP
6385INT wifi_setApWpsButtonPush(INT apIndex)
6386{
6387 char cmd[MAX_CMD_SIZE];
6388 char buf[MAX_BUF_SIZE]={0};
6389 BOOL enable=FALSE;
6390
6391 if(!(apIndex==0 || apIndex==1))
6392 return RETURN_ERR;
6393 wifi_getApEnable(apIndex, &enable);
6394 if (!enable)
6395 return RETURN_ERR;
6396
6397 wifi_getApWpsEnable(apIndex, &enable);
6398 if (!enable)
6399 return RETURN_ERR;
6400
6401 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6402 _syscmd(cmd, buf, sizeof(buf));
6403
6404 if((strstr(buf, "OK"))!=NULL)
6405 return RETURN_OK;
6406 return RETURN_ERR;
6407}
6408
6409// cancels WPS mode for this AP
6410INT wifi_cancelApWPS(INT apIndex)
6411{
6412 char cmd[MAX_CMD_SIZE];
6413 char buf[MAX_BUF_SIZE]={0};
6414
6415 if(!(apIndex==0 || apIndex==1))
6416 return RETURN_ERR;
6417 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6418 _syscmd(cmd,buf, sizeof(buf));
6419
6420 if((strstr(buf, "OK"))!=NULL)
6421 return RETURN_OK;
6422 return RETURN_ERR;
6423}
6424
6425//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6426//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6427INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6428{
6429 FILE *f;
6430 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6431 char cmd[256], buf[2048];
6432 char *param , *value, *line=NULL;
6433 size_t len = 0;
6434 ssize_t nread;
6435 wifi_associated_dev_t *dev=NULL;
6436
6437 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6438 *associated_dev_array = NULL;
6439 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6440 _syscmd(cmd,buf,sizeof(buf));
6441 *output_array_size = atoi(buf);
6442
6443 if (*output_array_size <= 0)
6444 return RETURN_OK;
6445
6446 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6447 *associated_dev_array = dev;
6448 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6449 _syscmd(cmd,buf,sizeof(buf));
6450 f = fopen("/tmp/connected_devices.txt", "r");
6451 if (f==NULL)
6452 {
6453 *output_array_size=0;
6454 return RETURN_ERR;
6455 }
6456 while ((nread = getline(&line, &len, f)) != -1)
6457 {
6458 param = strtok(line,"=");
6459 value = strtok(NULL,"=");
6460
6461 if( strcmp("flags",param) == 0 )
6462 {
6463 value[strlen(value)-1]='\0';
6464 if(strstr (value,"AUTHORIZED") != NULL )
6465 {
6466 dev[auth_temp].cli_AuthenticationState = 1;
6467 dev[auth_temp].cli_Active = 1;
6468 auth_temp++;
6469 read_flag=1;
6470 }
6471 }
6472 if(read_flag==1)
6473 {
6474 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6475 {
6476 value[strlen(value)-1]='\0';
6477 sscanf(value, "%x:%x:%x:%x:%x:%x",
6478 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6479 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6480 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6481 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6482 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6483 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6484 mac_temp++;
6485 read_flag=0;
6486 }
6487 }
6488 }
6489 *output_array_size = auth_temp;
6490 auth_temp=0;
6491 mac_temp=0;
6492 free(line);
6493 fclose(f);
6494 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6495 return RETURN_OK;
6496}
6497
6498#define MACADDRESS_SIZE 6
6499
6500INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6501{
6502 FILE *fp = NULL;
6503 char str[MAX_BUF_SIZE] = {0};
6504 int wificlientindex = 0 ;
6505 int count = 0;
6506 int signalstrength = 0;
6507 int arr[MACADDRESS_SIZE] = {0};
6508 unsigned char mac[MACADDRESS_SIZE] = {0};
6509 UINT wifi_count = 0;
6510 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6511 char pipeCmd[MAX_CMD_SIZE] = {0};
6512
6513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6514 *output_array_size = 0;
6515 *associated_dev_array = NULL;
6516
6517 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6518 fp = popen(pipeCmd, "r");
6519 if (fp == NULL)
6520 {
6521 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6522 return RETURN_ERR;
6523 }
6524
6525 /* Read the output a line at a time - output it. */
6526 fgets(str, sizeof(str)-1, fp);
6527 wifi_count = (unsigned int) atoi ( str );
6528 *output_array_size = wifi_count;
6529 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6530 pclose(fp);
6531
6532 if(wifi_count == 0)
6533 {
6534 return RETURN_OK;
6535 }
6536 else
6537 {
6538 wifi_associated_dev3_t* temp = NULL;
6539 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6540 if(temp == NULL)
6541 {
6542 printf("Error Statement. Insufficient memory \n");
6543 return RETURN_ERR;
6544 }
6545
6546 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6547 system(pipeCmd);
6548 memset(pipeCmd,0,sizeof(pipeCmd));
6549 if(apIndex == 0)
6550 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6551 else if(apIndex == 1)
6552 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6553 system(pipeCmd);
6554
6555 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6556 if(fp == NULL)
6557 {
6558 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6559 return RETURN_ERR;
6560 }
6561 fclose(fp);
6562
6563 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6564 fp = popen(pipeCmd, "r");
6565 if(fp)
6566 {
6567 for(count =0 ; count < wifi_count; count++)
6568 {
6569 fgets(str, MAX_BUF_SIZE, fp);
6570 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6571 {
6572 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6573 {
6574 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6575
6576 }
6577 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6578 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]);
6579 }
6580 temp[count].cli_AuthenticationState = 1; //TODO
6581 temp[count].cli_Active = 1; //TODO
6582 }
6583 pclose(fp);
6584 }
6585
6586 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6587 fp = popen(pipeCmd, "r");
6588 if(fp)
6589 {
6590 pclose(fp);
6591 }
6592 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6593 if(fp)
6594 {
6595 for(count =0 ; count < wifi_count ;count++)
6596 {
6597 fgets(str, MAX_BUF_SIZE, fp);
6598 signalstrength = atoi(str);
6599 temp[count].cli_SignalStrength = signalstrength;
6600 temp[count].cli_RSSI = signalstrength;
6601 temp[count].cli_SNR = signalstrength + 95;
6602 }
6603 pclose(fp);
6604 }
6605
6606
6607 if((apIndex == 0) || (apIndex == 4))
6608 {
6609 for(count =0 ; count < wifi_count ;count++)
6610 {
6611 strcpy(temp[count].cli_OperatingStandard,"g");
6612 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6613 }
6614
6615 //BytesSent
6616 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6617 fp = popen(pipeCmd, "r");
6618 if(fp)
6619 {
6620 pclose(fp);
6621 }
6622 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6623 if(fp)
6624 {
6625 for (count = 0; count < wifi_count; count++)
6626 {
6627 fgets(str, MAX_BUF_SIZE, fp);
6628 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6629 }
6630 pclose(fp);
6631 }
6632
6633 //BytesReceived
6634 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6635 fp = popen(pipeCmd, "r");
6636 if (fp)
6637 {
6638 pclose(fp);
6639 }
6640 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6641 if (fp)
6642 {
6643 for (count = 0; count < wifi_count; count++)
6644 {
6645 fgets(str, MAX_BUF_SIZE, fp);
6646 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
6647 }
6648 pclose(fp);
6649 }
6650
6651 //PacketsSent
6652 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
6653 fp = popen(pipeCmd, "r");
6654 if (fp)
6655 {
6656 pclose(fp);
6657 }
6658
6659 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
6660 if (fp)
6661 {
6662 for (count = 0; count < wifi_count; count++)
6663 {
6664 fgets(str, MAX_BUF_SIZE, fp);
6665 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
6666 }
6667 pclose(fp);
6668 }
6669
6670 //PacketsReceived
6671 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
6672 fp = popen(pipeCmd, "r");
6673 if (fp)
6674 {
6675 pclose(fp);
6676 }
6677 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
6678 if (fp)
6679 {
6680 for (count = 0; count < wifi_count; count++)
6681 {
6682 fgets(str, MAX_BUF_SIZE, fp);
6683 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
6684 }
6685 pclose(fp);
6686 }
6687
6688 //ErrorsSent
6689 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6690 fp = popen(pipeCmd, "r");
6691 if (fp)
6692 {
6693 pclose(fp);
6694 }
6695 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6696 if (fp)
6697 {
6698 for (count = 0; count < wifi_count; count++)
6699 {
6700 fgets(str, MAX_BUF_SIZE, fp);
6701 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6702 }
6703 pclose(fp);
6704 }
6705
6706 //ErrorsSent
6707 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6708 fp = popen(pipeCmd, "r");
6709 if (fp)
6710 {
6711 pclose(fp);
6712 }
6713 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6714 if (fp)
6715 {
6716 for (count = 0; count < wifi_count; count++)
6717 {
6718 fgets(str, MAX_BUF_SIZE, fp);
6719 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6720 }
6721 pclose(fp);
6722 }
6723
6724 //LastDataDownlinkRate
6725 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
6726 fp = popen(pipeCmd, "r");
6727 if (fp)
6728 {
6729 pclose(fp);
6730 }
6731 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
6732 if (fp)
6733 {
6734 for (count = 0; count < wifi_count; count++)
6735 {
6736 fgets(str, MAX_BUF_SIZE, fp);
6737 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
6738 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
6739 }
6740 pclose(fp);
6741 }
6742
6743 //LastDataUplinkRate
6744 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
6745 fp = popen(pipeCmd, "r");
6746 if (fp)
6747 {
6748 pclose(fp);
6749 }
6750 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
6751 if (fp)
6752 {
6753 for (count = 0; count < wifi_count; count++)
6754 {
6755 fgets(str, MAX_BUF_SIZE, fp);
6756 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
6757 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
6758 }
6759 pclose(fp);
6760 }
6761
6762 }
6763 else if ((apIndex == 1) || (apIndex == 5))
6764 {
6765 for (count = 0; count < wifi_count; count++)
6766 {
6767 strcpy(temp[count].cli_OperatingStandard, "a");
6768 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
6769 temp[count].cli_BytesSent = 0;
6770 temp[count].cli_BytesReceived = 0;
6771 temp[count].cli_LastDataUplinkRate = 0;
6772 temp[count].cli_LastDataDownlinkRate = 0;
6773 temp[count].cli_PacketsSent = 0;
6774 temp[count].cli_PacketsReceived = 0;
6775 temp[count].cli_ErrorsSent = 0;
6776 }
6777 }
6778
6779 for (count = 0; count < wifi_count; count++)
6780 {
6781 temp[count].cli_Retransmissions = 0;
6782 temp[count].cli_DataFramesSentAck = 0;
6783 temp[count].cli_DataFramesSentNoAck = 0;
6784 temp[count].cli_MinRSSI = 0;
6785 temp[count].cli_MaxRSSI = 0;
6786 strncpy(temp[count].cli_InterferenceSources, "", 64);
6787 memset(temp[count].cli_IPAddress, 0, 64);
6788 temp[count].cli_RetransCount = 0;
6789 temp[count].cli_FailedRetransCount = 0;
6790 temp[count].cli_RetryCount = 0;
6791 temp[count].cli_MultipleRetryCount = 0;
6792 }
6793 *associated_dev_array = temp;
6794 }
6795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6796 return RETURN_OK;
6797}
6798
6799int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
6800{
6801 FILE *fp = NULL;
6802 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
6803 char cmd[MAX_CMD_SIZE];
6804 int count = 0;
6805
6806 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6807 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
6808 fp = popen(cmd,"r");
6809 if(fp == NULL)
6810 {
6811 printf("Failed to run command in Function %s\n",__FUNCTION__);
6812 return 0;
6813 }
6814 if(fgets(path, sizeof(path)-1, fp) != NULL)
6815 {
6816 for(count=0;path[count]!='\n';count++)
6817 status[count]=path[count];
6818 status[count]='\0';
6819 }
6820 strcpy(wifi_status,status);
6821 pclose(fp);
6822 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6823 return RETURN_OK;
6824}
6825
6826/* #define HOSTAPD_STA_PARAM_ENTRIES 29
6827struct hostapd_sta_param {
6828 char key[50];
6829 char value[100];
6830}
6831
6832static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
6833 int i = 0;
6834
6835 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
6836 if (strncmp(params[i].key,key,50) == 0){
6837 return &params[i].value;
6838 }
6839 i++;
6840 }
6841 return NULL;
6842
6843} */
6844
6845static unsigned int count_occurences(const char *buf, const char *word)
6846{
6847 unsigned int n = 0;
6848 char *ptr = strstr(buf, word);
6849
6850 while (ptr++) {
6851 n++;
6852 ptr = strstr(ptr, word);
6853 }
6854
6855 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
6856 return n;
6857}
6858
6859static const char *get_line_from_str_buf(const char *buf, char *line)
6860{
6861 int i;
6862 int n = strlen(buf);
6863
6864 for (i = 0; i < n; i++) {
6865 line[i] = buf[i];
6866 if (buf[i] == '\n') {
6867 line[i] = '\0';
6868 return &buf[i + 1];
6869 }
6870 }
6871
6872 return NULL;
6873}
6874
6875INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6876{
6877 unsigned int assoc_cnt = 0;
6878 char interface_name[50] = {0};
6879 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
6880 char cmd[MAX_CMD_SIZE] = {'\0'};
6881 char line[256] = {'\0'};
6882 int i = 0;
6883 int ret = 0;
6884 const char *ptr = NULL;
6885 char *key = NULL;
6886 char *val = NULL;
6887 wifi_associated_dev3_t *temp = NULL;
6888 int rssi;
6889
6890 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6891
6892 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
6893 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
6894 return RETURN_ERR;
6895 }
6896
6897 // Example filtered output of 'iw dev' command:
6898 // Station 0a:69:72:10:d2:fa (on wifi0)
6899 // signal avg:-67 [-71, -71] dBm
6900 // Station 28:c2:1f:25:5f:99 (on wifi0)
6901 // signal avg:-67 [-71, -70] dBm
6902 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
6903 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
6904 return RETURN_ERR;
6905 }
6906
6907 ret = _syscmd(cmd, buf, sizeof(buf));
6908 if (ret == RETURN_ERR) {
6909 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
6910 return RETURN_ERR;
6911 }
6912
6913 *output_array_size = count_occurences(buf, "Station");
6914 if (*output_array_size == 0) return RETURN_OK;
6915
6916 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
6917 if (temp == NULL) {
6918 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
6919 return RETURN_ERR;
6920 }
6921 *associated_dev_array = temp;
6922
6923 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
6924 ptr = get_line_from_str_buf(buf, line);
6925 i = -1;
6926 while (ptr) {
6927 if (strstr(line, "Station")) {
6928 i++;
6929 key = strtok(line, " ");
6930 val = strtok(NULL, " ");
6931 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
6932 &temp[i].cli_MACAddress[0],
6933 &temp[i].cli_MACAddress[1],
6934 &temp[i].cli_MACAddress[2],
6935 &temp[i].cli_MACAddress[3],
6936 &temp[i].cli_MACAddress[4],
6937 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
6938 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
6939 free(*associated_dev_array);
6940 return RETURN_ERR;
6941 }
6942 }
6943 else if (i < 0) {
6944 ptr = get_line_from_str_buf(ptr, line);
6945 continue; // We didn't detect 'station' entry yet
6946 }
6947 else if (strstr(line, "signal avg")) {
6948 key = strtok(line, ":");
6949 val = strtok(NULL, " ");
6950 if (sscanf(val, "%d", &rssi) <= 0 ) {
6951 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
6952 free(*associated_dev_array);
6953 return RETURN_ERR;
6954 }
6955 temp[i].cli_RSSI = rssi;
6956 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
6957 }
6958 // Here other fields can be parsed if added to filter of 'iw dev' command
6959
6960 ptr = get_line_from_str_buf(ptr, line);
6961 };
6962
6963 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6964
6965 return RETURN_OK;
6966}
6967
6968#if 0
6969//To-do
6970INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6971{
6972 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6973
6974 //Using different approach to get required WiFi Parameters from system available commands
6975#if 0
6976 FILE *f;
6977 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6978 char cmd[256], buf[2048];
6979 char *param , *value, *line=NULL;
6980 size_t len = 0;
6981 ssize_t nread;
6982 wifi_associated_dev3_t *dev=NULL;
6983 *associated_dev_array = NULL;
6984 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6985 _syscmd(cmd,buf,sizeof(buf));
6986 *output_array_size = atoi(buf);
6987
6988 if (*output_array_size <= 0)
6989 return RETURN_OK;
6990
6991 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
6992 *associated_dev_array = dev;
6993 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
6994 _syscmd(cmd,buf,sizeof(buf));
6995 f = fopen("/tmp/connected_devices.txt", "r");
6996 if (f==NULL)
6997 {
6998 *output_array_size=0;
6999 return RETURN_ERR;
7000 }
7001 while ((nread = getline(&line, &len, f)) != -1)
7002 {
7003 param = strtok(line,"=");
7004 value = strtok(NULL,"=");
7005
7006 if( strcmp("flags",param) == 0 )
7007 {
7008 value[strlen(value)-1]='\0';
7009 if(strstr (value,"AUTHORIZED") != NULL )
7010 {
7011 dev[auth_temp].cli_AuthenticationState = 1;
7012 dev[auth_temp].cli_Active = 1;
7013 auth_temp++;
7014 read_flag=1;
7015 }
7016 }
7017 if(read_flag==1)
7018 {
7019 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7020 {
7021 value[strlen(value)-1]='\0';
7022 sscanf(value, "%x:%x:%x:%x:%x:%x",
7023 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7024 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7025 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7026 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7027 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7028 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7029
7030 }
7031 else if( strcmp("rx_packets",param) == 0 )
7032 {
7033 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7034 }
7035
7036 else if( strcmp("tx_packets",param) == 0 )
7037 {
7038 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7039 }
7040
7041 else if( strcmp("rx_bytes",param) == 0 )
7042 {
7043 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7044 }
7045
7046 else if( strcmp("tx_bytes",param) == 0 )
7047 {
7048 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7049 mac_temp++;
7050 read_flag=0;
7051 }
7052 }
7053 }
7054
7055 *output_array_size = auth_temp;
7056 auth_temp=0;
7057 mac_temp=0;
7058 free(line);
7059 fclose(f);
7060#endif
7061 char interface_name[MAX_BUF_SIZE] = {0};
7062 char wifi_status[MAX_BUF_SIZE] = {0};
7063 char hostapdconf[MAX_BUF_SIZE] = {0};
7064
7065 wifi_associated_dev3_t *dev_array = NULL;
7066 ULONG wifi_count = 0;
7067
7068 *associated_dev_array = NULL;
7069 *output_array_size = 0;
7070
7071 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7072 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7073 {
7074 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7075
7076 GetInterfaceName(interface_name, hostapdconf);
7077
7078 if(strlen(interface_name) > 1)
7079 {
7080 wifihal_interfacestatus(wifi_status,interface_name);
7081 if(strcmp(wifi_status,"RUNNING") == 0)
7082 {
7083 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7084
7085 *associated_dev_array = dev_array;
7086 *output_array_size = wifi_count;
7087 }
7088 else
7089 {
7090 *associated_dev_array = NULL;
7091 }
7092 }
7093 }
7094
7095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7096 return RETURN_OK;
7097}
7098#endif
7099
7100/* getIPAddress function */
7101/**
7102* @description Returning IpAddress of the Matched String
7103*
7104* @param
7105* @str Having MacAddress
7106* @ipaddr Having ipaddr
7107* @return The status of the operation
7108* @retval RETURN_OK if successful
7109* @retval RETURN_ERR if any error is detected
7110*
7111*/
7112
7113INT getIPAddress(char *str,char *ipaddr)
7114{
7115 FILE *fp = NULL;
7116 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7117 int LeaseTime = 0,ret = 0;
7118 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7119 {
7120 return RETURN_ERR;
7121 }
7122
7123 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7124 {
7125 /*
7126 Sample:sss
7127 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7128 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7129 */
7130 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7131 &(LeaseTime),
7132 phyAddr,
7133 ipAddr,
7134 hostName
7135 );
7136 if(ret != 4)
7137 continue;
7138 if(strcmp(str,phyAddr) == 0)
7139 strcpy(ipaddr,ipAddr);
7140 }
7141 return RETURN_OK;
7142}
7143
7144/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7145/**
7146* @description Returning Inactive wireless connected clients informations
7147*
7148* @param
7149* @filename Holding private_wifi 2g/5g content files
7150* @associated_dev_array Having inactiv wireless clients informations
7151* @output_array_size Returning Inactive wireless counts
7152* @return The status of the operation
7153* @retval RETURN_OK if successful
7154* @retval RETURN_ERR if any error is detected
7155*
7156*/
7157
7158INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7159{
7160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7161 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7162 FILE *fp = NULL;
7163 int arr[MACADDRESS_SIZE] = {0};
7164 unsigned char mac[MACADDRESS_SIZE] = {0};
7165 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7166 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7167 fp = popen(buf,"r");
7168 if(fp == NULL)
7169 return RETURN_ERR;
7170 else
7171 {
7172 fgets(path,sizeof(path),fp);
7173 maccount = atoi(path);
7174 }
7175 pclose(fp);
7176 *output_array_size = maccount;
7177 wifi_associated_dev3_t* temp = NULL;
7178 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7179 *associated_dev_array = temp;
7180 if(temp == NULL)
7181 {
7182 printf("Error Statement. Insufficient memory \n");
7183 return RETURN_ERR;
7184 }
7185 memset(buf,0,sizeof(buf));
7186 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7187 fp = popen(buf,"r");
7188 for(count = 0; count < maccount ; count++)
7189 {
7190 fgets(path,sizeof(path),fp);
7191 for(i = 0; path[i]!='\n';i++)
7192 str[i]=path[i];
7193 str[i]='\0';
7194 getIPAddress(str,ipaddr);
7195 memset(buf,0,sizeof(buf));
7196 if(strlen(ipaddr) > 0)
7197 {
7198 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7199 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7200 {
7201 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7202 {
7203 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7204 {
7205 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7206
7207 }
7208 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7209 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]);
7210 }
7211 temp[count].cli_AuthenticationState = 0; //TODO
7212 temp[count].cli_Active = 0; //TODO
7213 temp[count].cli_SignalStrength = 0;
7214 }
7215 else //Active wireless clients info
7216 {
7217 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7218 {
7219 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7220 {
7221 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7222
7223 }
7224 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7225 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]);
7226 }
7227 temp[count].cli_Active = 1;
7228 }
7229 }
7230 memset(ipaddr,0,sizeof(ipaddr));
7231 }
7232 pclose(fp);
7233 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7234 return RETURN_OK;
7235}
7236//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7237//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7238//To get Band Steering Capability
7239INT wifi_getBandSteeringCapability(BOOL *support)
7240{
7241 *support = FALSE;
7242 return RETURN_OK;
7243}
7244
7245
7246//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7247//To get Band Steering enable status
7248INT wifi_getBandSteeringEnable(BOOL *enable)
7249{
7250 *enable = FALSE;
7251 return RETURN_OK;
7252}
7253
7254//To turn on/off Band steering
7255INT wifi_setBandSteeringEnable(BOOL enable)
7256{
7257 return RETURN_OK;
7258}
7259
7260//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7261//To get Band Steering AP group
7262INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7263{
7264 if (NULL == output_ApGroup)
7265 return RETURN_ERR;
7266
7267 strcpy(output_ApGroup, "1,2");
7268 return RETURN_OK;
7269}
7270
7271//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7272//to set and read the band steering BandUtilizationThreshold parameters
7273INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7274{
7275 return RETURN_ERR;
7276}
7277
7278INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7279{
7280 return RETURN_ERR;
7281}
7282
7283//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7284//to set and read the band steering RSSIThreshold parameters
7285INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7286{
7287 return RETURN_ERR;
7288}
7289
7290INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7291{
7292 return RETURN_ERR;
7293}
7294
7295
7296//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7297//to set and read the band steering physical modulation rate threshold parameters
7298INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7299{
7300 //If chip is not support, return -1
7301 return RETURN_ERR;
7302}
7303
7304INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7305{
7306 //If chip is not support, return -1
7307 return RETURN_ERR;
7308}
7309
7310//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7311//to set and read the inactivity time (in seconds) for steering under overload condition
7312INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7313{
7314 return RETURN_ERR;
7315}
7316
7317INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7318{
7319 return RETURN_ERR;
7320}
7321
7322//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7323//to set and read the inactivity time (in seconds) for steering under Idle condition
7324INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7325{
7326 return RETURN_ERR;
7327}
7328
7329INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7330{
7331 return RETURN_ERR;
7332}
7333
7334//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7335//pClientMAC[64]
7336//pSourceSSIDIndex[64]
7337//pDestSSIDIndex[64]
7338//pSteeringReason[256]
7339INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7340{
7341 //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
7342 *pSteeringTime=time(NULL);
7343 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7344 return RETURN_OK;
7345}
7346
7347INT wifi_ifConfigDown(INT apIndex)
7348{
7349 INT status = RETURN_OK;
7350 char cmd[64];
7351
7352 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7353 printf("%s: %s\n", __func__, cmd);
7354 system(cmd);
7355
7356 return status;
7357}
7358
7359INT wifi_ifConfigUp(INT apIndex)
7360{
7361 char cmd[128];
7362 char buf[1024];
7363
7364 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7365 _syscmd(cmd, buf, sizeof(buf));
7366 return 0;
7367}
7368
7369//>> Deprecated. Replace with wifi_applyRadioSettings
7370INT wifi_pushBridgeInfo(INT apIndex)
7371{
7372 char ip[32];
7373 char subnet[32];
7374 char bridge[32];
7375 int vlanId;
7376 char cmd[128];
7377 char buf[1024];
7378
7379 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7380 wifi_getApVlanID(apIndex,&vlanId);
7381
7382 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7383 _syscmd(cmd,buf, sizeof(buf));
7384
7385 return 0;
7386}
7387
7388INT wifi_pushChannel(INT radioIndex, UINT channel)
7389{
7390 char cmd[128];
7391 char buf[1024];
7392 int apIndex;
7393
7394 apIndex=(radioIndex==0)?0:1;
7395 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7396 _syscmd(cmd,buf, sizeof(buf));
7397
7398 return 0;
7399}
7400
7401INT wifi_pushChannelMode(INT radioIndex)
7402{
7403 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7404 return RETURN_ERR;
7405}
7406
7407INT wifi_pushDefaultValues(INT radioIndex)
7408{
7409 //Apply Comcast specified default radio settings instantly
7410 //AMPDU=1
7411 //AMPDUFrames=32
7412 //AMPDULim=50000
7413 //txqueuelen=1000
7414
7415 return RETURN_ERR;
7416}
7417
7418INT wifi_pushTxChainMask(INT radioIndex)
7419{
7420 //Apply default TxChainMask instantly
7421 return RETURN_ERR;
7422}
7423
7424INT wifi_pushRxChainMask(INT radioIndex)
7425{
7426 //Apply default RxChainMask instantly
7427 return RETURN_ERR;
7428}
7429
7430INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7431{
7432 INT status;
7433
7434 status = wifi_setSSIDName(apIndex,ssid);
7435 wifi_setApEnable(apIndex,FALSE);
7436 wifi_setApEnable(apIndex,TRUE);
7437
7438 return status;
7439}
7440
7441INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7442{
7443 //Apply default Ssid Advertisement instantly
7444 return RETURN_ERR;
7445}
7446
7447INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7448{
7449 INT status = RETURN_ERR;
7450 *output = 0;
7451 return RETURN_ERR;
7452}
7453
7454INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7455{
7456 return RETURN_OK;
7457}
7458
7459INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7460{
7461 return RETURN_OK;
7462}
7463
7464//To-do
7465INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7466{
developereb199ae2022-09-13 14:04:27 +08007467 char output[16]={'\0'};
7468 char config_file[MAX_BUF_SIZE] = {0};
7469
7470 if (!output_string)
7471 return RETURN_ERR;
7472
7473 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7474 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7475
7476 if (strlen(output) == 0)
7477 snprintf(output_string, 64, "Disabled");
7478 else if (strncmp(output, "0", 1) == 0)
7479 snprintf(output_string, 64, "Disabled");
7480 else if (strncmp(output, "1", 1) == 0)
7481 snprintf(output_string, 64, "Optional");
7482 else if (strncmp(output, "2", 1) == 0)
7483 snprintf(output_string, 64, "Required");
7484 else {
7485 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7486 return RETURN_ERR;
7487 }
7488
7489 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007490 return RETURN_OK;
7491}
7492INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7493{
developereb199ae2022-09-13 14:04:27 +08007494 char str[MAX_BUF_SIZE]={'\0'};
7495 char cmd[MAX_CMD_SIZE]={'\0'};
7496 struct params params;
7497 char config_file[MAX_BUF_SIZE] = {0};
7498
7499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7500 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7501 return RETURN_ERR;
7502
7503 params.name = "ieee80211w";
7504 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7505 params.value = "0";
7506 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7507 params.value = "1";
7508 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7509 params.value = "2";
7510 else{
7511 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7512 return RETURN_ERR;
7513 }
7514 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7515 wifi_hostapdWrite(config_file, &params, 1);
7516 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007517 return RETURN_OK;
7518}
7519INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7520{
7521 char output[16]={'\0'};
7522 char config_file[MAX_BUF_SIZE] = {0};
7523
7524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7525 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7526 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7527
7528 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7529 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7530
7531 return RETURN_OK;
7532}
7533
7534INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7535{
7536 return RETURN_OK;
7537}
7538
7539INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7540{
7541 return RETURN_OK;
7542}
7543
7544INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7545{
7546 return RETURN_OK;
7547}
7548
7549INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7550{
7551 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7552 char config_file[MAX_BUF_SIZE] = {0};
7553
7554 if (NULL == output)
7555 return RETURN_ERR;
7556 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7557 wifi_hostapdRead(config_file,"hw_mode",output,64);
7558
7559 if(strcmp(output,"b")==0)
7560 sprintf(output, "%s", "1,2,5.5,11");
7561 else if (strcmp(output,"a")==0)
7562 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7563 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7564 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7565
7566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7567 return RETURN_OK;
7568}
7569
7570INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7571{
7572 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7573 char *temp;
7574 char temp_output[128];
7575 char temp_TransmitRates[128];
7576 char config_file[MAX_BUF_SIZE] = {0};
7577
7578 if (NULL == output)
7579 return RETURN_ERR;
7580
7581 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7582 wifi_hostapdRead(config_file,"supported_rates",output,64);
7583
7584 strcpy(temp_TransmitRates,output);
7585 strcpy(temp_output,"");
7586 temp = strtok(temp_TransmitRates," ");
7587 while(temp!=NULL)
7588 {
7589 temp[strlen(temp)-1]=0;
7590 if((temp[0]=='5') && (temp[1]=='\0'))
7591 {
7592 temp="5.5";
7593 }
7594 strcat(temp_output,temp);
7595 temp = strtok(NULL," ");
7596 if(temp!=NULL)
7597 {
7598 strcat(temp_output,",");
7599 }
7600 }
7601 strcpy(output,temp_output);
7602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7603
7604 return RETURN_OK;
7605}
7606
7607INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7608{
7609 return RETURN_OK;
7610}
7611
7612
7613INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7614{
7615 int i=0;
7616 char *temp;
7617 char temp1[128];
7618 char temp_output[128];
7619 char temp_TransmitRates[128];
7620 struct params params={'\0'};
7621 char config_file[MAX_BUF_SIZE] = {0};
7622
7623 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7624 if(NULL == output)
7625 return RETURN_ERR;
7626
7627 strcpy(temp_TransmitRates,output);
7628
7629 for(i=0;i<strlen(temp_TransmitRates);i++)
7630 {
7631 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7632 {
7633 continue;
7634 }
7635 else
7636 {
7637 return RETURN_ERR;
7638 }
7639 }
7640 strcpy(temp_output,"");
7641 temp = strtok(temp_TransmitRates," ");
7642 while(temp!=NULL)
7643 {
7644 strcpy(temp1,temp);
7645 if(wlanIndex==1)
7646 {
7647 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
7648 {
7649 return RETURN_ERR;
7650 }
7651 }
7652
7653 if(strcmp(temp,"5.5")==0)
7654 {
7655 strcpy(temp1,"55");
7656 }
7657 else
7658 {
7659 strcat(temp1,"0");
7660 }
7661 strcat(temp_output,temp1);
7662 temp = strtok(NULL," ");
7663 if(temp!=NULL)
7664 {
7665 strcat(temp_output," ");
7666 }
7667 }
7668 strcpy(output,temp_output);
7669
7670
7671 params.name = "supported_rates";
7672 params.value = output;
7673
7674 wifi_dbg_printf("\n%s:",__func__);
7675 wifi_dbg_printf("params.value=%s\n",params.value);
7676 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7677 wifi_hostapdWrite(config_file,&params,1);
7678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7679
7680 return RETURN_OK;
7681}
7682
7683
7684static char *sncopy(char *dst, int dst_sz, const char *src)
7685{
7686 if (src && dst && dst_sz > 0) {
7687 strncpy(dst, src, dst_sz);
7688 dst[dst_sz - 1] = '\0';
7689 }
7690 return dst;
7691}
7692
7693static int util_get_sec_chan_offset(int channel, const char* ht_mode)
7694{
7695 if (0 == strcmp(ht_mode, "HT40") ||
7696 0 == strcmp(ht_mode, "HT80") ||
7697 0 == strcmp(ht_mode, "HT160")) {
7698 switch (channel) {
7699 case 1 ... 7:
7700 case 36:
7701 case 44:
7702 case 52:
7703 case 60:
7704 case 100:
7705 case 108:
7706 case 116:
7707 case 124:
7708 case 132:
7709 case 140:
7710 case 149:
7711 case 157:
7712 return 1;
7713 case 8 ... 13:
7714 case 40:
7715 case 48:
7716 case 56:
7717 case 64:
7718 case 104:
7719 case 112:
7720 case 120:
7721 case 128:
7722 case 136:
7723 case 144:
7724 case 153:
7725 case 161:
7726 return -1;
7727 default:
7728 return -EINVAL;
7729 }
7730 }
7731
7732 return -EINVAL;
7733}
7734
7735static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
7736{
7737 if (NULL == hw_mode) return;
7738
7739 if (0 == strcmp(hw_mode, "ac"))
7740 sncopy(bw_mode, bw_mode_len, "ht vht");
7741
7742 if (0 == strcmp(hw_mode, "n"))
7743 sncopy(bw_mode, bw_mode_len, "ht");
7744
7745 return;
7746}
7747
7748static int util_chan_to_freq(int chan)
7749{
7750 if (chan == 14)
7751 return 2484;
7752 else if (chan < 14)
7753 return 2407 + chan * 5;
7754 else if (chan >= 182 && chan <= 196)
7755 return 4000 + chan * 5;
7756 else
7757 return 5000 + chan * 5;
7758 return 0;
7759}
7760
7761const int *util_unii_5g_chan2list(int chan, int width)
7762{
7763 static const int lists[] = {
7764 // <width>, <chan1>, <chan2>..., 0,
7765 20, 36, 0,
7766 20, 40, 0,
7767 20, 44, 0,
7768 20, 48, 0,
7769 20, 52, 0,
7770 20, 56, 0,
7771 20, 60, 0,
7772 20, 64, 0,
7773 20, 100, 0,
7774 20, 104, 0,
7775 20, 108, 0,
7776 20, 112, 0,
7777 20, 116, 0,
7778 20, 120, 0,
7779 20, 124, 0,
7780 20, 128, 0,
7781 20, 132, 0,
7782 20, 136, 0,
7783 20, 140, 0,
7784 20, 144, 0,
7785 20, 149, 0,
7786 20, 153, 0,
7787 20, 157, 0,
7788 20, 161, 0,
7789 20, 165, 0,
7790 40, 36, 40, 0,
7791 40, 44, 48, 0,
7792 40, 52, 56, 0,
7793 40, 60, 64, 0,
7794 40, 100, 104, 0,
7795 40, 108, 112, 0,
7796 40, 116, 120, 0,
7797 40, 124, 128, 0,
7798 40, 132, 136, 0,
7799 40, 140, 144, 0,
7800 40, 149, 153, 0,
7801 40, 157, 161, 0,
7802 80, 36, 40, 44, 48, 0,
7803 80, 52, 56, 60, 64, 0,
7804 80, 100, 104, 108, 112, 0,
7805 80, 116, 120, 124, 128, 0,
7806 80, 132, 136, 140, 144, 0,
7807 80, 149, 153, 157, 161, 0,
7808 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
7809 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
7810 -1 // final delimiter
7811 };
7812 const int *start;
7813 const int *p;
7814
7815 for (p = lists; *p != -1; p++) {
7816 if (*p == width) {
7817 for (start = ++p; *p != 0; p++) {
7818 if (*p == chan)
7819 return start;
7820 }
7821 }
7822 // move to the end of channel list of given width
7823 while (*p != 0) {
7824 p++;
7825 }
7826 }
7827
7828 return NULL;
7829}
7830
7831static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
7832{
7833 if (NULL == ht_mode)
7834 return 0;
7835
7836 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
7837 const int *chans = util_unii_5g_chan2list(channel, width);
7838 int sum = 0;
7839 int cnt = 0;
7840
7841 if (NULL == chans)
7842 return 0;
7843
7844 while (*chans) {
7845 sum += *chans;
7846 cnt++;
7847 chans++;
7848 }
7849 return sum / cnt;
7850}
7851
7852static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
7853{
7854 BOOL onlyG, onlyN, onlyA;
7855 CHAR tmp[64];
7856 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
7857 if (ret == RETURN_OK) {
7858 sncopy(hw_mode, hw_mode_size, tmp);
7859 }
7860 return ret;
7861}
7862
7863INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
7864{
7865 // Sample commands:
7866 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
7867 // hostapd_cli -i wifi0 chan_switch 30 2437
7868 char cmd[MAX_CMD_SIZE] = {0};
7869 char buf[MAX_BUF_SIZE] = {0};
7870 int freq = 0, ret = 0;
7871 char center_freq1_str[32] = ""; // center_freq1=%d
7872 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
7873 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
7874 char hw_mode[16] = ""; // n|ac
7875 char bw_mode[16] = ""; // ht|ht vht
7876 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
7877 int sec_chan_offset;
7878 int width;
7879
7880 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7881
7882 freq = util_chan_to_freq(channel);
7883
7884 // Get radio mode HT20|HT40|HT80 etc.
7885 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
7886 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
7887 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
7888 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
7889 if (sec_chan_offset != -EINVAL)
7890 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
7891
7892
7893 // Provide bandwith if specified
7894 if (channel_width_MHz > 20) {
7895 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
7896 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
7897 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
7898
7899 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
7900 }
7901
7902 int center_chan = 0;
7903 if (channel_width_MHz > 20) {
7904 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
7905 if (center_chan > 0) {
7906 int center_freq1 = util_chan_to_freq(center_chan);
7907 if (center_freq1)
7908 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
7909 }
7910 }
7911
7912 {
7913 // Only the first AP, other are hanging on the same radio
7914 int apIndex = radioIndex;
7915 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
7916 AP_PREFIX, apIndex, csa_beacon_count, freq,
7917 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
7918 wifi_dbg_printf("execute: '%s'\n", cmd);
7919 ret = _syscmd(cmd, buf, sizeof(buf));
7920 }
7921
7922 wifi_setRadioChannel(radioIndex, channel);
7923
7924 char *ext_str = "None";
7925 if (sec_chan_offset == 1) ext_str = "Above";
7926 else if (sec_chan_offset == -1) ext_str = "Below";
7927 wifi_setRadioExtChannel(radioIndex, ext_str);
7928
7929 wifi_setRadioCenterChannel(radioIndex, center_chan);
7930
7931 char mhz_str[16];
7932 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
7933 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
7934
7935 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7936
7937 return RETURN_OK;
7938}
7939
7940INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
7941{
7942 char cmd[1024] = {0};
7943 char buf[1024] = {0};
7944 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7945 wifi_neighbor_ap2_t *scan_array = NULL;
7946 int scan_count=0;
7947 int i =0;
7948 int freq=0;
7949 size_t len=0;
7950 FILE *f = NULL;
7951 ssize_t read = 0;
7952 char *line =NULL;
7953 char radio_ifname[64];
7954 char secondary_chan[64];
7955 int vht_channel_width = 0;
7956
7957 if(wifi_getRadioIfName(radio_index,radio_ifname)!=RETURN_OK)
7958 return RETURN_ERR;
7959
7960 /* sched_start is not supported on open source ath9k ath10k firmware
7961 * Using active scan as a workaround */
7962 sprintf(cmd,"iw dev %s scan |grep '^BSS\\|SSID:\\|freq:\\|signal:\\|HT operation:\\|secondary channel offset:\\|* channel width:'", radio_ifname);
7963 if((f = popen(cmd, "r")) == NULL) {
7964 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
7965 return RETURN_ERR;
7966 }
7967 read = getline(&line, &len, f);
7968 while (read != -1) {
7969 if(strncmp(line,"BSS",3) == 0) {
7970 i = scan_count;
7971 scan_count++;
7972 scan_array = realloc(scan_array,sizeof(wifi_neighbor_ap2_t)*scan_count);
7973 memset(&(scan_array[i]),0, sizeof(wifi_neighbor_ap2_t));
7974 sscanf(line,"BSS %17s", scan_array[i].ap_BSSID);
7975
7976 read = getline(&line, &len, f);
7977 sscanf(line," freq: %d", &freq);
7978 scan_array[i].ap_Channel = ieee80211_frequency_to_channel(freq);
7979
7980 read = getline(&line, &len, f);
7981 sscanf(line," signal: %d", &(scan_array[i].ap_SignalStrength));
7982
7983 read = getline(&line, &len, f);
7984 sscanf(line," SSID: %s", scan_array[i].ap_SSID);
7985 wifi_dbg_printf("%s:Discovered BSS %s, %d, %d , %s\n", __func__, scan_array[i].ap_BSSID, scan_array[i].ap_Channel,scan_array[i].ap_SignalStrength, scan_array[i].ap_SSID);
7986 read = getline(&line, &len, f);
7987 if(strncmp(line,"BSS",3)==0) {
7988 // No HT and no VHT => 20Mhz
7989 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11%s", radio_index%1 ? "A": "G");
7990 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7991 continue;
7992 }
7993 if(strncmp(line," HT operation:",14)!= 0) {
7994 wifi_dbg_printf("HT output parsing error (%s)\n", line);
7995 goto output_error;
7996 }
7997
7998 read = getline(&line, &len, f);
7999 sscanf(line," * secondary channel offset: %s", &secondary_chan);
8000
8001 if(!strcmp(secondary_chan, "no")) {
8002 //20Mhz
8003 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
8004 }
8005
8006 if(!strcmp(secondary_chan, "above")) {
8007 //40Mhz +
8008 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
8009 }
8010
8011 if(!strcmp(secondary_chan, "below")) {
8012 //40Mhz -
8013 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8014 }
8015
8016
8017 read = getline(&line, &len, f);
8018 if(strncmp(line," VHT operation:",15) !=0) {
8019 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
8020 // No VHT
8021 continue;
8022 }
8023 read = getline(&line, &len, f);
8024 sscanf(line," * channel width: %d", &vht_channel_width);
8025 if(vht_channel_width == 1) {
8026 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT80");
8027 } else {
8028 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT40");
8029 }
8030
8031 }
8032 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
8033 read = getline(&line, &len, f);
8034 }
8035 wifi_dbg_printf("%s:Counted BSS: %d\n",__func__, scan_count);
8036 *output_array_size = scan_count;
8037 *neighbor_ap_array = scan_array;
8038 free(line);
8039 pclose(f);
8040 return RETURN_OK;
8041
8042output_error:
8043 pclose(f);
8044 free(line);
8045 free(scan_array);
8046 return RETURN_ERR;
8047}
8048INT wifi_getApAssociatedDeviceStats(
8049 INT apIndex,
8050 mac_address_t *clientMacAddress,
8051 wifi_associated_dev_stats_t *associated_dev_stats,
8052 u64 *handle)
8053{
8054 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8055 char interface_name[50] = {0};
8056 char cmd[1024] = {0};
8057 char mac_str[18] = {0};
8058 char *key = NULL;
8059 char *val = NULL;
8060 FILE *f = NULL;
8061 char *line = NULL;
8062 size_t len = 0;
8063 ssize_t read = 0;
8064
8065 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8066 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8067 return RETURN_ERR;
8068 }
8069
8070 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8071 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8072 if((f = popen(cmd, "r")) == NULL) {
8073 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8074 return RETURN_ERR;
8075 }
8076
8077 while ((read = getline(&line, &len, f)) != -1) {
8078 key = strtok(line,":");
8079 val = strtok(NULL,":");
8080
8081 if(!strncmp(key,"rx bytes",8))
8082 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8083 if(!strncmp(key,"tx bytes",8))
8084 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8085 if(!strncmp(key,"rx packets",10))
8086 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8087 if(!strncmp(key,"tx packets",10))
8088 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8089 if(!strncmp(key,"tx retries",10))
8090 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8091 if(!strncmp(key,"tx failed",9))
8092 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8093 if(!strncmp(key,"rx drop misc",13))
8094 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8095 if(!strncmp(key,"rx bitrate",10)) {
8096 val = strtok(val, " ");
8097 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8098 }
8099 if(!strncmp(key,"tx bitrate",10)) {
8100 val = strtok(val, " ");
8101 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8102 }
8103 }
8104 free(line);
8105 pclose(f);
8106 return RETURN_OK;
8107}
8108
8109INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8110{
8111 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8112
8113 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8114 if (NULL == output_string)
8115 return RETURN_ERR;
8116
8117 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8118 _syscmd(cmd, buf, sizeof(buf));
8119
8120 //size of SSID name restricted to value less than 32 bytes
8121 snprintf(output_string, 32, "%s", buf);
8122 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8123
8124 return RETURN_OK;
8125}
8126
8127INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8128{
8129 //char cmd[MAX_CMD_SIZE] = {0};
8130 char config_file[MAX_BUF_SIZE] = {0};
8131 char buf[32] = {0};
8132
8133 if (!output_filterMode)
8134 return RETURN_ERR;
8135
8136 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8137 //_syscmd(cmd, buf, sizeof(buf));
8138 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8139 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008140 if(strlen(buf) == 0) {
8141 *output_filterMode = 0;
8142 }
8143 else {
8144 int macaddr_acl_mode = strtol(buf, NULL, 10);
8145 if (macaddr_acl_mode == 1) {
8146 *output_filterMode = 1;
8147 } else if (macaddr_acl_mode == 0) {
8148 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8149 if (strlen(buf) == 0) {
8150 *output_filterMode = 0;
8151 } else {
8152 *output_filterMode = 2;
8153 }
8154 } else {
8155 return RETURN_ERR;
8156 }
8157 }
developer06a01d92022-09-07 16:32:39 +08008158
8159 return RETURN_OK;
8160}
8161
8162INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8163{
8164 FILE *fp = NULL;
8165 char str[MAX_BUF_SIZE] = {0};
8166 int wificlientindex = 0 ;
8167 int count = 0;
8168 int signalstrength = 0;
8169 int arr[MACADDRESS_SIZE] = {0};
8170 unsigned char mac[MACADDRESS_SIZE] = {0};
8171 UINT wifi_count = 0;
8172 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8173 char pipeCmd[MAX_CMD_SIZE] = {0};
8174
8175 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8176 *output_array_size = 0;
8177 *associated_dev_array = NULL;
8178 char interface_name[50] = {0};
8179
8180 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8181 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8182 return RETURN_ERR;
8183 }
8184
8185 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8186 fp = popen(pipeCmd, "r");
8187 if (fp == NULL)
8188 {
8189 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8190 return RETURN_ERR;
8191 }
8192
8193 /* Read the output a line at a time - output it. */
8194 fgets(str, sizeof(str)-1, fp);
8195 wifi_count = (unsigned int) atoi ( str );
8196 *output_array_size = wifi_count;
8197 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8198 pclose(fp);
8199
8200 if(wifi_count == 0)
8201 {
8202 return RETURN_OK;
8203 }
8204 else
8205 {
8206 wifi_associated_dev2_t* temp = NULL;
8207 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8208 *associated_dev_array = temp;
8209 if(temp == NULL)
8210 {
8211 printf("Error Statement. Insufficient memory \n");
8212 return RETURN_ERR;
8213 }
8214
8215 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8216 system(pipeCmd);
8217
8218 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8219 if(fp == NULL)
8220 {
8221 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8222 return RETURN_ERR;
8223 }
8224 fclose(fp);
8225
8226 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8227 fp = popen(pipeCmd, "r");
8228 if(fp)
8229 {
8230 for(count =0 ; count < wifi_count; count++)
8231 {
8232 fgets(str, MAX_BUF_SIZE, fp);
8233 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8234 {
8235 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8236 {
8237 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8238
8239 }
8240 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8241 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]);
8242 }
8243 temp[count].cli_AuthenticationState = 1; //TODO
8244 temp[count].cli_Active = 1; //TODO
8245 }
8246 pclose(fp);
8247 }
8248
8249 //Updating RSSI per client
8250 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8251 fp = popen(pipeCmd, "r");
8252 if(fp)
8253 {
8254 pclose(fp);
8255 }
8256 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8257 if(fp)
8258 {
8259 for(count =0 ; count < wifi_count ;count++)
8260 {
8261 fgets(str, MAX_BUF_SIZE, fp);
8262 signalstrength = atoi(str);
8263 temp[count].cli_RSSI = signalstrength;
8264 }
8265 pclose(fp);
8266 }
8267
8268
8269 //LastDataDownlinkRate
8270 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8271 fp = popen(pipeCmd, "r");
8272 if (fp)
8273 {
8274 pclose(fp);
8275 }
8276 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8277 if (fp)
8278 {
8279 for (count = 0; count < wifi_count; count++)
8280 {
8281 fgets(str, MAX_BUF_SIZE, fp);
8282 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8283 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8284 }
8285 pclose(fp);
8286 }
8287
8288 //LastDataUplinkRate
8289 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8290 fp = popen(pipeCmd, "r");
8291 if (fp)
8292 {
8293 pclose(fp);
8294 }
8295 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8296 if (fp)
8297 {
8298 for (count = 0; count < wifi_count; count++)
8299 {
8300 fgets(str, MAX_BUF_SIZE, fp);
8301 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8302 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8303 }
8304 pclose(fp);
8305 }
8306 }
8307 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8308 return RETURN_OK;
8309
8310}
8311
8312INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8313{
8314#if 0
8315 /*char buf[1024] = {0};
8316 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8317 _syscmd(cmd, buf, sizeof(buf));*/
8318
8319 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8320 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8321 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8322 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8323
8324 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.
8325 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].
8326 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].
8327 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].
8328 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8329 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8330
8331 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8332 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8333 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8334 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.
8335 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.
8336 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.
8337 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.
8338 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.
8339 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.
8340 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.
8341 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8342#endif
8343
8344 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008345 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008346 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008347 char pipeCmd[128] = {0};
8348 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008349 wifi_ssidTrafficStats2_t *out = output_struct;
8350
developerce736392022-09-13 15:24:34 +08008351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008352 if (!output_struct)
8353 return RETURN_ERR;
8354
developerce736392022-09-13 15:24:34 +08008355 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8356 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8357 GetInterfaceName(interface_name, HConf_file);
8358 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008359
developer06a01d92022-09-07 16:32:39 +08008360 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008361 if (fp == NULL) {
8362 fprintf(stderr, "%s: popen failed\n", __func__);
8363 return RETURN_ERR;
8364 }
8365 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008366
developerce736392022-09-13 15:24:34 +08008367 if (strlen(str) == 0) // interface not exist
8368 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008369
developerce736392022-09-13 15:24:34 +08008370 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8371 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008372 pclose(fp);
8373
developerce736392022-09-13 15:24:34 +08008374 memset(str, 0, sizeof(str));
8375 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008376 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008377 if (fp == NULL) {
8378 fprintf(stderr, "%s: popen failed\n", __func__);
8379 return RETURN_ERR;
8380 }
8381 fgets(str, sizeof(str), fp);
8382
8383 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8384 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008385 pclose(fp);
developerce736392022-09-13 15:24:34 +08008386
8387 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8388 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8389
8390 // Not supported
8391 output_struct->ssid_RetransCount = 0;
8392 output_struct->ssid_FailedRetransCount = 0;
8393 output_struct->ssid_RetryCount = 0;
8394 output_struct->ssid_MultipleRetryCount = 0;
8395 output_struct->ssid_ACKFailureCount = 0;
8396 output_struct->ssid_AggregatedPacketCount = 0;
8397
developer06a01d92022-09-07 16:32:39 +08008398 return RETURN_OK;
8399}
8400
8401//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).
8402INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8403{
8404 char output_val[16]={'\0'};
8405 char config_file[MAX_BUF_SIZE] = {0};
8406
8407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8408 if (!output)
8409 return RETURN_ERR;
8410 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8411 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8412
8413 if( strcmp(output_val,"1") == 0 )
8414 *output = TRUE;
8415 else
8416 *output = FALSE;
8417 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8418
8419 return RETURN_OK;
8420}
8421
8422INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8423{
8424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8425 char str[MAX_BUF_SIZE]={'\0'};
8426 char string[MAX_BUF_SIZE]={'\0'};
8427 char cmd[MAX_CMD_SIZE]={'\0'};
8428 char *ch;
8429 char config_file[MAX_BUF_SIZE] = {0};
8430 struct params params;
8431
8432 if(enable == TRUE)
8433 strcpy(string,"1");
8434 else
8435 strcpy(string,"0");
8436
8437 params.name = "ap_isolate";
8438 params.value = string;
8439
8440 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8441 wifi_hostapdWrite(config_file,&params,1);
8442 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8443
8444 return RETURN_OK;
8445}
8446
8447INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8448{
8449 if (NULL == output_dBm)
8450 return RETURN_ERR;
8451
8452 *output_dBm = 0;
8453 return RETURN_OK;
8454}
8455
8456INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8457{
8458 return RETURN_OK;
8459}
8460INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8461{
8462 return RETURN_OK;
8463}
8464INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8465{
8466 return RETURN_OK;
8467}
8468INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8469{
8470 return RETURN_OK;
8471}
8472INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8473{
8474 return RETURN_OK;
8475}
8476INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8477{
8478 char config_file[MAX_BUF_SIZE] = {0};
8479 struct params list;
8480
8481 list.name = "bss_transition";
8482 list.value = activate?"1":"0";
8483 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8484 wifi_hostapdWrite(config_file, &list, 1);
8485
8486 return RETURN_OK;
8487}
8488wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8489
8490void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8491{
8492 return;
8493}
8494
8495INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8496{
8497 // TODO Implement me!
8498 return RETURN_OK;
8499}
8500
8501INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8502{
developera3c68b92022-09-13 15:27:29 +08008503 char file_name[128] = {0};
8504 char buf[128] = {0};
8505 FILE *f = NULL;
8506
8507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8508
8509 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8510 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8511 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8512 f = fopen(file_name, "w");
8513 if (f == NULL)
8514 return RETURN_ERR;
8515 // For mode == 0 is to disable filter, just don't write to the file.
8516 if (mode)
8517 fprintf(f, "%s", essid);
8518
8519 fclose(f);
8520 }
8521 } else { // special case, need to set AP's SSID as filter for each radio.
8522 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8523 f = fopen(file_name, "w");
8524 if (f == NULL)
8525 return RETURN_ERR;
8526
8527 // For mode == 0 is to disable filter, just don't write to the file.
8528 if (mode)
8529 fprintf(f, "%s", essid);
8530
8531 fclose(f);
8532 }
8533
8534 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008535 return RETURN_OK;
8536}
8537
8538INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
8539{
8540 // TODO Implement me!
8541 //Apply wifi_pushRadioChannel() instantly
8542 return RETURN_ERR;
8543}
8544
8545INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
8546{
8547 // TODO Implement me!
8548 return RETURN_OK;
8549}
8550
8551#ifdef HAL_NETLINK_IMPL
8552static int tidStats_callback(struct nl_msg *msg, void *arg) {
8553 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8554 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8555 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8556 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
8557 int rem , tid_index = 0;
8558
8559 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
8560 wifi_associated_dev_tid_entry_t *stats_entry;
8561
8562 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
8563 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
8564 };
8565 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
8566 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
8567 };
8568
8569 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8570 genlmsg_attrlen(gnlh, 0), NULL);
8571
8572
8573 if (!tb[NL80211_ATTR_STA_INFO]) {
8574 fprintf(stderr, "station stats missing!\n");
8575 return NL_SKIP;
8576 }
8577
8578 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
8579 tb[NL80211_ATTR_STA_INFO],
8580 stats_policy)) {
8581 fprintf(stderr, "failed to parse nested attributes!\n");
8582 return NL_SKIP;
8583 }
8584
8585 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
8586 {
8587 stats_entry = &out->tid_array[tid_index];
8588
8589 stats_entry->tid = tid_index;
8590 stats_entry->ac = _tid_ac_index_get[tid_index];
8591
8592 if(sinfo[NL80211_STA_INFO_TID_STATS])
8593 {
8594 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
8595 printf("failed to parse nested stats attributes!");
8596 return NL_SKIP;
8597 }
8598 }
8599 if(stats_info[NL80211_TID_STATS_TX_MSDU])
8600 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
8601
8602 if(tid_index < (PS_MAX_TID - 1))
8603 tid_index++;
8604 }
8605 //ToDo: sum_time_ms, ewma_time_ms
8606 return NL_SKIP;
8607}
8608#endif
8609
8610INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
8611{
8612#ifdef HAL_NETLINK_IMPL
8613 Netlink nl;
8614 char if_name[10];
8615
8616 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8617
8618 nl.id = initSock80211(&nl);
8619
8620 if (nl.id < 0) {
8621 fprintf(stderr, "Error initializing netlink \n");
8622 return -1;
8623 }
8624
8625 struct nl_msg* msg = nlmsg_alloc();
8626
8627 if (!msg) {
8628 fprintf(stderr, "Failed to allocate netlink message.\n");
8629 nlfree(&nl);
8630 return -2;
8631 }
8632
8633 genlmsg_put(msg,
8634 NL_AUTO_PORT,
8635 NL_AUTO_SEQ,
8636 nl.id,
8637 0,
8638 0,
8639 NL80211_CMD_GET_STATION,
8640 0);
8641
8642 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
8643 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8644 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
8645 nl_send_auto(nl.socket, msg);
8646 nl_recvmsgs(nl.socket, nl.cb);
8647 nlmsg_free(msg);
8648 nlfree(&nl);
8649 return RETURN_OK;
8650#else
8651//iw implementation
8652#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
8653#define TOTAL_MAX_LINES 50
8654
8655 char buf[256] = {'\0'}; /* or other suitable maximum line size */
8656 char if_name[10];
8657 FILE *fp=NULL;
8658 char pipeCmd[1024]= {'\0'};
8659 int lines,tid_index=0;
8660 char mac_addr[20] = {'\0'};
8661
8662 wifi_associated_dev_tid_entry_t *stats_entry;
8663
8664 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8665 strcpy(mac_addr,clientMacAddress);
8666
8667 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
8668 fp= popen(pipeCmd,"r");
8669 if(fp == NULL)
8670 {
8671 perror("popen for station dump failed\n");
8672 return RETURN_ERR;
8673 }
8674 pclose(fp);
8675
8676 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
8677 fp=popen(pipeCmd,"r");
8678 if(fp == NULL)
8679 {
8680 perror("popen for grep station failed\n");
8681 return RETURN_ERR;
8682 }
8683 else if(fgets(buf,sizeof(buf),fp) != NULL)
8684 lines=atoi(buf);
8685 else
8686 {
8687 pclose(fp);
8688 fprintf(stderr,"No devices are connected \n");
8689 return RETURN_ERR;
8690 }
8691 pclose(fp);
8692
8693 if(lines == 1)
8694 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
8695
8696 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
8697 {
8698 stats_entry = &tid_stats->tid_array[tid_index];
8699 stats_entry->tid = tid_index;
8700
8701 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);
8702
8703 fp=popen(pipeCmd,"r");
8704 if(fp ==NULL)
8705 {
8706 perror("Failed to read from tid file \n");
8707 return RETURN_ERR;
8708 }
8709 else if(fgets(buf,sizeof(buf),fp) != NULL)
8710 stats_entry->num_msdus = atol(buf);
8711
8712 pclose(fp);
8713 stats_entry->ac = _tid_ac_index_get[tid_index];
8714// TODO:
8715// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
8716// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
8717 }
8718 return RETURN_OK;
8719#endif
8720}
8721
8722
8723INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
8724{
8725 // TODO Implement me!
8726 return RETURN_OK;
8727}
8728
8729
8730INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
8731{
8732 // TODO Implement me!
8733 return RETURN_ERR;
8734}
8735
8736INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
8737{
8738 // TODO Implement me!
8739 return RETURN_ERR;
8740}
8741
8742INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
8743{
8744 // TODO Implement me!
8745 return RETURN_ERR;
8746}
8747
8748INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
8749{
8750 // TODO Implement me!
8751 return RETURN_ERR;
8752}
8753
8754INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
8755{
8756 // TODO Implement me!
8757 return RETURN_ERR;
8758}
8759
8760INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
8761{
8762 // TODO Implement me!
8763 return RETURN_ERR;
8764}
8765
8766INT wifi_steering_eventUnregister(void)
8767{
8768 // TODO Implement me!
8769 return RETURN_ERR;
8770}
8771
8772INT wifi_delApAclDevices(INT apIndex)
8773{
8774#if 0
8775 char cmd[MAX_BUF_SIZE] = {0};
8776 char buf[MAX_BUF_SIZE] = {0};
8777
8778 /* Not reset proof solution */
8779 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
8780 if(_syscmd(cmd,buf,sizeof(buf)))
8781 return RETURN_ERR;
8782#endif
developere6aafda2022-09-13 14:59:28 +08008783 char cmd[MAX_CMD_SIZE]={0};
8784 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08008785
developere6aafda2022-09-13 14:59:28 +08008786 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8787 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
8788 if(_syscmd(cmd, buf, sizeof(buf)))
8789 return RETURN_ERR;
8790 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008791
8792 return RETURN_OK;
8793}
8794
8795#ifdef HAL_NETLINK_IMPL
8796static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
8797 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8798 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8799 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8800 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
8801 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
8802 char mac_addr[20],dev[20];
8803
8804 nla_parse(tb,
8805 NL80211_ATTR_MAX,
8806 genlmsg_attrdata(gnlh, 0),
8807 genlmsg_attrlen(gnlh, 0),
8808 NULL);
8809
8810 if(!tb[NL80211_ATTR_STA_INFO]) {
8811 fprintf(stderr, "sta stats missing!\n");
8812 return NL_SKIP;
8813 }
8814
8815 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
8816 fprintf(stderr, "failed to parse nested attributes!\n");
8817 return NL_SKIP;
8818 }
8819 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
8820
8821 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8822
8823 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
8824 fprintf(stderr, "failed to parse nested rate attributes!");
8825 return NL_SKIP;
8826 }
8827
8828 if(sinfo[NL80211_STA_INFO_TID_STATS])
8829 {
8830 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
8831 printf("failed to parse nested stats attributes!");
8832 return NL_SKIP;
8833 }
8834 }
8835
8836 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
8837 {
8838 printf("Type is VHT\n");
8839 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
8840 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
8841
8842 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
8843 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
8844 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
8845 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8846 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
8847 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8848 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
8849 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8850 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
8851 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
8852 }
8853 else
8854 {
8855 printf(" OFDM or CCK \n");
8856 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
8857 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
8858 }
8859
8860 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
8861 if(rinfo[NL80211_RATE_INFO_MCS])
8862 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
8863 }
8864 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
8865 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
8866 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
8867 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
8868
8869 if(stats_info[NL80211_TID_STATS_RX_MSDU])
8870 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
8871
8872 if (sinfo[NL80211_STA_INFO_SIGNAL])
8873 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
8874 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
8875 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
8876 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
8877 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
8878 //rssi_array need to be filled
8879 return NL_SKIP;
8880}
8881#endif
8882
8883INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
8884{
8885#ifdef HAL_NETLINK_IMPL
8886 Netlink nl;
8887 char if_name[10];
8888
8889 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
8890
8891 if (*output_array_size <= 0)
8892 return RETURN_OK;
8893
8894 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8895 nl.id = initSock80211(&nl);
8896
8897 if (nl.id < 0) {
8898 fprintf(stderr, "Error initializing netlink \n");
8899 return 0;
8900 }
8901
8902 struct nl_msg* msg = nlmsg_alloc();
8903
8904 if (!msg) {
8905 fprintf(stderr, "Failed to allocate netlink message.\n");
8906 nlfree(&nl);
8907 return 0;
8908 }
8909
8910 genlmsg_put(msg,
8911 NL_AUTO_PORT,
8912 NL_AUTO_SEQ,
8913 nl.id,
8914 0,
8915 0,
8916 NL80211_CMD_GET_STATION,
8917 0);
8918
8919 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
8920 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8921 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
8922 nl_send_auto(nl.socket, msg);
8923 nl_recvmsgs(nl.socket, nl.cb);
8924 nlmsg_free(msg);
8925 nlfree(&nl);
8926 return RETURN_OK;
8927#else
8928 //TODO Implement me
8929 return RETURN_OK;
8930#endif
8931}
8932
8933#ifdef HAL_NETLINK_IMPL
8934static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
8935 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8936 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8937 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8938 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
8939 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
8940 char mac_addr[20],dev[20];
8941
8942 nla_parse(tb,
8943 NL80211_ATTR_MAX,
8944 genlmsg_attrdata(gnlh, 0),
8945 genlmsg_attrlen(gnlh, 0),
8946 NULL);
8947
8948 if(!tb[NL80211_ATTR_STA_INFO]) {
8949 fprintf(stderr, "sta stats missing!\n");
8950 return NL_SKIP;
8951 }
8952
8953 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
8954 fprintf(stderr, "failed to parse nested attributes!\n");
8955 return NL_SKIP;
8956 }
8957
8958 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
8959
8960 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8961
8962 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
8963 fprintf(stderr, "failed to parse nested rate attributes!");
8964 return NL_SKIP;
8965 }
8966
8967 if(sinfo[NL80211_STA_INFO_TID_STATS])
8968 {
8969 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
8970 printf("failed to parse nested stats attributes!");
8971 return NL_SKIP;
8972 }
8973 }
8974 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
8975 {
8976 printf("Type is VHT\n");
8977 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
8978 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
8979
8980 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
8981 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
8982 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
8983 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8984 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
8985 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8986 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
8987 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8988 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
8989 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
8990 }
8991 else
8992 {
8993 printf(" OFDM or CCK \n");
8994 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
8995 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
8996 }
8997
8998 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
8999 if(rinfo[NL80211_RATE_INFO_MCS])
9000 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9001 }
9002
9003 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9004 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9005 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9006 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9007
9008 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9009 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9010 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9011
9012 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9013 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9014
9015 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9016 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9017
9018 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9019 ((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]);
9020
9021 return NL_SKIP;
9022}
9023#endif
9024
9025INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9026{
9027#ifdef HAL_NETLINK_IMPL
9028 Netlink nl;
9029 char if_name[10];
9030
9031 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9032
9033 if (*output_array_size <= 0)
9034 return RETURN_OK;
9035
9036 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9037
9038 nl.id = initSock80211(&nl);
9039
9040 if(nl.id < 0) {
9041 fprintf(stderr, "Error initializing netlink \n");
9042 return 0;
9043 }
9044
9045 struct nl_msg* msg = nlmsg_alloc();
9046
9047 if(!msg) {
9048 fprintf(stderr, "Failed to allocate netlink message.\n");
9049 nlfree(&nl);
9050 return 0;
9051 }
9052
9053 genlmsg_put(msg,
9054 NL_AUTO_PORT,
9055 NL_AUTO_SEQ,
9056 nl.id,
9057 0,
9058 0,
9059 NL80211_CMD_GET_STATION,
9060 0);
9061
9062 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9063 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9064 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9065 nl_send_auto(nl.socket, msg);
9066 nl_recvmsgs(nl.socket, nl.cb);
9067 nlmsg_free(msg);
9068 nlfree(&nl);
9069 return RETURN_OK;
9070#else
9071 //TODO Implement me
9072 return RETURN_OK;
9073#endif
9074}
9075
9076INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9077{
9078 // TODO Implement me!
9079 char buf[MAX_BUF_SIZE] = {0};
9080 char config_file[MAX_BUF_SIZE] = {0};
9081
9082 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9083 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9084 *activate = (strncmp("1",buf,1) == 0);
9085
9086 return RETURN_OK;
9087}
9088
9089INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9090{
9091 char config_file[MAX_BUF_SIZE] = {0};
9092 struct params list;
9093
9094 list.name = "rrm_neighbor_report";
9095 list.value = activate?"1":"0";
9096 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9097 wifi_hostapdWrite(config_file, &list, 1);
9098
9099 return RETURN_OK;
9100}
9101
9102INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9103{
9104 char buf[32] = {0};
9105 char config_file[MAX_BUF_SIZE] = {0};
9106
9107 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9108 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9109 *activate = (strncmp("1",buf,1) == 0);
9110
9111 return RETURN_OK;
9112}
9113#undef HAL_NETLINK_IMPL
9114#ifdef HAL_NETLINK_IMPL
9115static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9116 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9117 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9118 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9119 char dev[20];
9120 int freq =0 ;
9121 static int i=0;
9122
9123 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9124
9125 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9126 };
9127
9128 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9129
9130 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9131
9132 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9133 fprintf(stderr, "survey data missing!\n");
9134 return NL_SKIP;
9135 }
9136
9137 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9138 {
9139 fprintf(stderr, "failed to parse nested attributes!\n");
9140 return NL_SKIP;
9141 }
9142
9143
9144 if(out[0].array_size == 1 )
9145 {
9146 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9147 {
9148 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9149 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9150 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9151
9152 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9153 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9154 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9155 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9156 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9157 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9158 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9159 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9160 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9161 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9162 if (sinfo[NL80211_SURVEY_INFO_TIME])
9163 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9164 return NL_STOP;
9165 }
9166 }
9167 else
9168 {
9169 if ( i <= out[0].array_size )
9170 {
9171 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9172 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9173 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9174
9175 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9176 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9177 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9178 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9179 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9180 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9181 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9182 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9183 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9184 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9185 if (sinfo[NL80211_SURVEY_INFO_TIME])
9186 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9187 }
9188 }
9189
9190 i++;
9191 return NL_SKIP;
9192}
9193#endif
9194
9195static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9196{
9197 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9198 FILE *fp;
9199
9200 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9201 {
9202 printf("Creating Frequency-Channel Map\n");
9203 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9204 }
9205 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9206 if((fp = popen(command, "r")))
9207 {
9208 fgets(output, sizeof(output), fp);
9209 *freqMHz = atoi(output);
9210 fclose(fp);
9211 }
9212
9213 return 0;
9214}
9215
9216static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9217{
9218 int freqMHz = -1;
9219 char cmd[MAX_CMD_SIZE] = {'\0'};
9220
9221 ieee80211_channel_to_frequency(channel, &freqMHz);
9222 if (freqMHz == -1) {
9223 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9224 return -1;
9225 }
9226
9227 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9228 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9229 radioIndex, freqMHz);
9230 return -1;
9231 }
9232
9233 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9234 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9235 return -1;
9236 }
9237
9238 return 0;
9239}
9240
9241static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9242{
9243 const char *ptr = buf;
9244 char *key = NULL;
9245 char *val = NULL;
9246 char line[256] = { '\0' };
9247
9248 while (ptr = get_line_from_str_buf(ptr, line)) {
9249 if (strstr(line, "Frequency")) continue;
9250
9251 key = strtok(line, ":");
9252 val = strtok(NULL, " ");
9253 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9254
9255 if (!strcmp(key, "noise")) {
9256 sscanf(val, "%d", &stats->ch_noise);
9257 if (stats->ch_noise == 0) {
9258 // Workaround for missing noise information.
9259 // Assume -95 for 2.4G and -103 for 5G
9260 if (radioIndex == 0) stats->ch_noise = -95;
9261 if (radioIndex == 1) stats->ch_noise = -103;
9262 }
9263 }
9264 else if (!strcmp(key, "channel active time")) {
9265 sscanf(val, "%llu", &stats->ch_utilization_total);
9266 }
9267 else if (!strcmp(key, "channel busy time")) {
9268 sscanf(val, "%llu", &stats->ch_utilization_busy);
9269 }
9270 else if (!strcmp(key, "channel receive time")) {
9271 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9272 }
9273 else if (!strcmp(key, "channel transmit time")) {
9274 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9275 }
9276 };
9277
9278 return 0;
9279}
9280
9281INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9282{
9283 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9284#ifdef HAL_NETLINK_IMPL
9285 Netlink nl;
9286 wifi_channelStats_t_loc local[array_size];
9287 char if_name[10];
9288
9289 local[0].array_size = array_size;
9290
9291 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9292
9293 nl.id = initSock80211(&nl);
9294
9295 if (nl.id < 0) {
9296 fprintf(stderr, "Error initializing netlink \n");
9297 return -1;
9298 }
9299
9300 struct nl_msg* msg = nlmsg_alloc();
9301
9302 if (!msg) {
9303 fprintf(stderr, "Failed to allocate netlink message.\n");
9304 nlfree(&nl);
9305 return -2;
9306 }
9307
9308 genlmsg_put(msg,
9309 NL_AUTO_PORT,
9310 NL_AUTO_SEQ,
9311 nl.id,
9312 0,
9313 NLM_F_DUMP,
9314 NL80211_CMD_GET_SURVEY,
9315 0);
9316
9317 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9318 nl_send_auto(nl.socket, msg);
9319 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9320 nl_recvmsgs(nl.socket, nl.cb);
9321 nlmsg_free(msg);
9322 nlfree(&nl);
9323 //Copying the Values
9324 for(int i=0;i<array_size;i++)
9325 {
9326 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9327 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9328 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9329 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9330 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9331 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9332 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9333 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9334 }
9335#else
9336 ULONG channel = 0;
9337 int i;
9338 int number_of_channels = array_size;
9339 char buf[512];
9340 INT ret;
9341 wifi_channelStats_t tmp_stats;
9342
9343 if (number_of_channels == 0) {
9344 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9345 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9346 return RETURN_ERR;
9347 }
9348 number_of_channels = 1;
9349 input_output_channelStats_array[0].ch_number = channel;
9350 }
9351
9352 for (i = 0; i < number_of_channels; i++) {
9353
9354 input_output_channelStats_array[i].ch_noise = 0;
9355 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9356 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9357 input_output_channelStats_array[i].ch_utilization_busy = 0;
9358 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9359 input_output_channelStats_array[i].ch_utilization_total = 0;
9360
9361 memset(buf, 0, sizeof(buf));
9362 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9363 return RETURN_ERR;
9364 }
9365 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9366 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9367 return RETURN_ERR;
9368 }
9369
9370 // XXX: fake missing 'self' counter which is not available in iw survey output
9371 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9372 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9373
9374 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9375 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9376 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9377 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9378 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9379
9380 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",
9381 __func__,
9382 input_output_channelStats_array[i].ch_number,
9383 input_output_channelStats_array[i].ch_noise,
9384 input_output_channelStats_array[i].ch_utilization_total,
9385 input_output_channelStats_array[i].ch_utilization_busy,
9386 input_output_channelStats_array[i].ch_utilization_busy_rx,
9387 input_output_channelStats_array[i].ch_utilization_busy_tx,
9388 input_output_channelStats_array[i].ch_utilization_busy_self,
9389 input_output_channelStats_array[i].ch_utilization_busy_ext);
9390 }
9391#endif
9392 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9393 return RETURN_OK;
9394}
9395#define HAL_NETLINK_IMPL
9396
9397/* Hostapd events */
9398
9399#ifndef container_of
9400#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9401#define container_of(ptr, type, member) \
9402 ((type *)((char *)ptr - offset_of(type, member)))
9403#endif /* container_of */
9404
9405struct ctrl {
9406 char sockpath[128];
9407 char sockdir[128];
9408 char bss[IFNAMSIZ];
9409 char reply[4096];
9410 int ssid_index;
9411 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9412 void (*overrun)(struct ctrl *ctrl);
9413 struct wpa_ctrl *wpa;
9414 unsigned int ovfl;
9415 size_t reply_len;
9416 int initialized;
9417 ev_timer retry;
9418 ev_timer watchdog;
9419 ev_stat stat;
9420 ev_io io;
9421};
9422static wifi_newApAssociatedDevice_callback clients_connect_cb;
9423static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9424static struct ctrl wpa_ctrl[MAX_APS];
9425static int initialized;
9426
9427static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9428{
9429 char cbuf[256] = {};
9430 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9431 struct cmsghdr *cmsg;
9432 unsigned int ovfl = ctrl->ovfl;
9433 unsigned int drop;
9434
9435 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9436 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9437 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9438 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9439
9440 drop = ovfl - ctrl->ovfl;
9441 ctrl->ovfl = ovfl;
9442
9443 return drop;
9444}
9445
9446static void ctrl_close(struct ctrl *ctrl)
9447{
9448 if (ctrl->io.cb)
9449 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9450 if (ctrl->retry.cb)
9451 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9452 if (!ctrl->wpa)
9453 return;
9454
9455 wpa_ctrl_detach(ctrl->wpa);
9456 wpa_ctrl_close(ctrl->wpa);
9457 ctrl->wpa = NULL;
9458 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9459}
9460
9461static void ctrl_process(struct ctrl *ctrl)
9462{
9463 const char *str;
9464 int drops;
9465 int level;
9466 int err;
9467
9468 /* Example events:
9469 *
9470 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9471 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9472 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9473 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9474 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9475 */
9476 if (!(str = index(ctrl->reply, '>')))
9477 return;
9478 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9479 return;
9480
9481 str++;
9482
9483 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9484 if (!(str = index(ctrl->reply, ' ')))
9485 return;
9486 wifi_associated_dev_t sta;
9487 memset(&sta, 0, sizeof(sta));
9488
9489 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9490 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9491 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9492
9493 sta.cli_Active=true;
9494
9495 (clients_connect_cb)(ctrl->ssid_index, &sta);
9496 goto handled;
9497 }
9498
9499 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9500 if (!(str = index(ctrl->reply, ' ')))
9501 return;
9502
9503 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9504 goto handled;
9505 }
9506
9507 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9508 printf("CTRL_WPA: handle TERMINATING event\n");
9509 goto retry;
9510 }
9511
9512 if (strncmp("AP-DISABLED", str, 11) == 0) {
9513 printf("CTRL_WPA: handle AP-DISABLED\n");
9514 goto retry;
9515 }
9516
9517 printf("Event not supported!!\n");
9518
9519handled:
9520
9521 if ((drops = ctrl_get_drops(ctrl))) {
9522 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
9523 if (ctrl->overrun)
9524 ctrl->overrun(ctrl);
9525 }
9526
9527 return;
9528
9529retry:
9530 printf("WPA_CTRL: closing\n");
9531 ctrl_close(ctrl);
9532 printf("WPA_CTRL: retrying from ctrl prcoess\n");
9533 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
9534}
9535
9536static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
9537{
9538 struct ctrl *ctrl = container_of(io, struct ctrl, io);
9539 int err;
9540
9541 memset(ctrl->reply, 0, sizeof(ctrl->reply));
9542 ctrl->reply_len = sizeof(ctrl->reply) - 1;
9543 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
9544 ctrl->reply[ctrl->reply_len] = 0;
9545 if (err < 0) {
9546 if (errno == EAGAIN || errno == EWOULDBLOCK)
9547 return;
9548 ctrl_close(ctrl);
9549 ev_timer_again(EV_A_ &ctrl->retry);
9550 return;
9551 }
9552
9553 ctrl_process(ctrl);
9554}
9555
9556static int ctrl_open(struct ctrl *ctrl)
9557{
9558 int fd;
9559
9560 if (ctrl->wpa)
9561 return 0;
9562
9563 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
9564 if (!ctrl->wpa)
9565 goto err;
9566
9567 if (wpa_ctrl_attach(ctrl->wpa) < 0)
9568 goto err_close;
9569
9570 fd = wpa_ctrl_get_fd(ctrl->wpa);
9571 if (fd < 0)
9572 goto err_detach;
9573
9574 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
9575 goto err_detach;
9576
9577 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
9578 ev_io_start(EV_DEFAULT_ &ctrl->io);
9579
9580 return 0;
9581
9582err_detach:
9583 wpa_ctrl_detach(ctrl->wpa);
9584err_close:
9585 wpa_ctrl_close(ctrl->wpa);
9586err:
9587 ctrl->wpa = NULL;
9588 return -1;
9589}
9590
9591static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
9592{
9593 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
9594
9595 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
9596 ctrl_open(ctrl);
9597}
9598
9599static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
9600{
9601 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
9602
9603 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
9604 if (ctrl_open(ctrl) == 0) {
9605 printf("WPA_CTRL: retry successful\n");
9606 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9607 }
9608}
9609
9610int ctrl_enable(struct ctrl *ctrl)
9611{
9612 if (ctrl->wpa)
9613 return 0;
9614
9615 if (!ctrl->stat.cb) {
9616 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
9617 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
9618 }
9619
9620 if (!ctrl->retry.cb) {
9621 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
9622 }
9623
9624 return ctrl_open(ctrl);
9625}
9626
9627static void
9628ctrl_msg_cb(char *buf, size_t len)
9629{
9630 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
9631
9632 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
9633 ctrl_process(ctrl);
9634}
9635
9636static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
9637{
9638 int err;
9639
9640 if (!ctrl->wpa)
9641 return -1;
9642 if (*reply_len < 2)
9643 return -1;
9644
9645 (*reply_len)--;
9646 ctrl->reply_len = sizeof(ctrl->reply);
9647 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
9648 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
9649 if (err < 0)
9650 return err;
9651
9652 if (ctrl->reply_len > *reply_len)
9653 ctrl->reply_len = *reply_len;
9654
9655 *reply_len = ctrl->reply_len;
9656 memcpy(reply, ctrl->reply, *reply_len);
9657 reply[*reply_len - 1] = 0;
9658 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
9659 return 0;
9660}
9661
9662static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
9663{
9664 const char *pong = "PONG";
9665 const char *ping = "PING";
9666 char reply[1024];
9667 size_t len = sizeof(reply);
9668 int err;
9669 ULONG s, snum;
9670 INT ret;
9671 BOOL status;
9672
9673 printf("WPA_CTRL: watchdog cb\n");
9674
9675 ret = wifi_getSSIDNumberOfEntries(&snum);
9676 if (ret != RETURN_OK) {
9677 printf("%s: failed to get SSID count", __func__);
9678 return;
9679 }
9680
9681 if (snum > MAX_APS) {
9682 printf("more ssid than supported! %lu\n", snum);
9683 return;
9684 }
9685
9686 for (s = 0; s < snum; s++) {
9687 if (wifi_getApEnable(s, &status) != RETURN_OK) {
9688 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
9689 continue;
9690 }
9691 if (status == false) continue;
9692
9693 memset(reply, 0, sizeof(reply));
9694 len = sizeof(reply);
9695 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
9696 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
9697 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
9698 continue;
9699
9700 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
9701 ctrl_close(&wpa_ctrl[s]);
9702 printf("WPA_CTRL: ev_timer_again %d\n", s);
9703 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
9704 }
9705}
9706
9707static int init_wpa()
9708{
9709 int ret = 0, i = 0;
9710 ULONG s, snum;
9711
9712 ret = wifi_getSSIDNumberOfEntries(&snum);
9713 if (ret != RETURN_OK) {
9714 printf("%s: failed to get SSID count", __func__);
9715 return RETURN_ERR;
9716 }
9717
9718 if (snum > MAX_APS) {
9719 printf("more ssid than supported! %lu\n", snum);
9720 return RETURN_ERR;
9721 }
9722
9723 for (s = 0; s < snum; s++) {
9724 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
9725 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
9726 wpa_ctrl[s].ssid_index = s;
9727 ctrl_enable(&wpa_ctrl[s]);
9728 }
9729
9730 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
9731 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
9732
9733 initialized = 1;
9734 printf("WPA_CTRL: initialized\n");
9735
9736 return RETURN_OK;
9737}
9738
9739void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
9740{
9741 clients_connect_cb = callback_proc;
9742 if (!initialized)
9743 init_wpa();
9744}
9745
9746void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
9747{
9748 clients_disconnect_cb = callback_proc;
9749 if (!initialized)
9750 init_wpa();
9751}
9752
9753INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
9754{
9755 // TODO Implement me!
9756 return RETURN_ERR;
9757}
9758
9759INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
9760{
9761 // TODO Implement me!
9762 return RETURN_ERR;
9763}
9764
9765INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
9766{
9767 int i;
9768 char cmd[256];
9769 char channel_numbers_buf[256];
9770 char dfs_state_buf[256];
9771 char line[256];
9772 const char *ptr;
9773
9774 memset(cmd, 0, sizeof(cmd));
9775 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
9776 memset(line, 0, sizeof(line));
9777 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
9778 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
9779
9780 if (radioIndex == 0) { // 2.4G - all allowed
9781 if (outputMapSize < 11) {
9782 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
9783 return RETURN_ERR;
9784 }
9785
9786 for (i = 0; i < 11; i++) {
9787 outputMap[i].ch_number = i + 1;
9788 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
9789 }
9790
9791 return RETURN_OK;
9792 }
9793
9794 if (radioIndex == 1) { // 5G
9795// Example output of iw list:
9796//
9797// Frequencies:
9798// * 5180 MHz [36] (17.0 dBm)
9799// * 5200 MHz [40] (17.0 dBm)
9800// * 5220 MHz [44] (17.0 dBm)
9801// * 5240 MHz [48] (17.0 dBm)
9802// * 5260 MHz [52] (23.0 dBm) (radar detection)
9803// DFS state: usable (for 78930 sec)
9804// DFS CAC time: 60000 ms
9805// * 5280 MHz [56] (23.0 dBm) (radar detection)
9806// DFS state: usable (for 78930 sec)
9807// DFS CAC time: 60000 ms
9808// * 5300 MHz [60] (23.0 dBm) (radar detection)
9809// DFS state: usable (for 78930 sec)
9810// DFS CAC time: 60000 ms
9811// * 5320 MHz [64] (23.0 dBm) (radar detection)
9812// DFS state: usable (for 78930 sec)
9813// DFS CAC time: 60000 ms
9814// * 5500 MHz [100] (disabled)
9815// * 5520 MHz [104] (disabled)
9816// * 5540 MHz [108] (disabled)
9817// * 5560 MHz [112] (disabled)
9818//
9819// Below command should fetch channel numbers of each enabled channel in 5GHz band:
9820 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
9821 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
9822 return RETURN_ERR;
9823 }
9824
9825 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
9826 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9827 return RETURN_ERR;
9828 }
9829
9830 ptr = channel_numbers_buf;
9831 i = 0;
9832 while (ptr = get_line_from_str_buf(ptr, line)) {
9833 if (i >= outputMapSize) {
9834 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
9835 return RETURN_ERR;
9836 }
9837 sscanf(line, "%d", &outputMap[i].ch_number);
9838
9839 memset(cmd, 0, sizeof(cmd));
9840 // Below command should fetch string for DFS state (usable, available or unavailable)
9841 // Example line: "DFS state: usable (for 78930 sec)"
9842 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) {
9843 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
9844 return RETURN_ERR;
9845 }
9846
9847 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
9848 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
9849 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9850 return RETURN_ERR;
9851 }
9852
9853 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
9854
9855 if (!strcmp(dfs_state_buf, "usable")) {
9856 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
9857 } else if (!strcmp(dfs_state_buf, "available")) {
9858 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
9859 } else if (!strcmp(dfs_state_buf, "unavailable")) {
9860 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
9861 } else {
9862 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
9863 }
9864 i++;
9865 }
9866
9867 return RETURN_OK;
9868 }
9869
9870 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
9871 return RETURN_ERR;
9872}
9873
9874INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
9875{
9876 // TODO Implement me!
9877 return RETURN_ERR;
9878}
9879
9880INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
9881{
9882 return RETURN_OK;
9883}
9884
9885INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
9886{
9887 // TODO Implement me!
9888 return RETURN_ERR;
9889}
9890
9891INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
9892{
9893 // TODO API refrence Implementaion is present on RPI hal
9894 return RETURN_ERR;
9895}
9896
9897INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
9898{
developera5005b62022-09-13 15:43:35 +08009899 char cmd[128]={'\0'};
9900 char buf[128]={'\0'};
9901 char *support;
9902 int maximum_tx = 0, current_tx = 0;
9903
9904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9905 if(txpwr_pcntg == NULL)
9906 return RETURN_ERR;
9907
9908 // Get the maximum tx power of the device
9909 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
9910 _syscmd(cmd, buf, sizeof(buf));
9911 maximum_tx = strtol(buf, NULL, 10);
9912
9913 // Get the current tx power
9914 memset(cmd, 0, sizeof(cmd));
9915 memset(buf, 0, sizeof(buf));
9916 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
9917 _syscmd(cmd, buf, sizeof(buf));
9918 current_tx = strtol(buf, NULL, 10);
9919
9920 // Get the power supported list and find the current power percentage in supported list
9921 memset(buf, 0, sizeof(buf));
9922 wifi_getRadioTransmitPowerSupported(apIndex, buf);
9923 support = strtok(buf, ",");
9924 while(true)
9925 {
9926 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
9927 *txpwr_pcntg = 0;
9928 wifi_dbg_printf("current power is not in supported list\n");
9929 return RETURN_ERR;
9930 }
9931 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
9932 if (tmp == current_tx) {
9933 *txpwr_pcntg = strtol(support, NULL, 10);
9934 break;
9935 }
9936 support = strtok(NULL, ",");
9937 }
9938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009939 return RETURN_OK;
9940}
9941
9942INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
9943{
developer58599c22022-09-13 16:40:34 +08009944 // TODO precac feature.
9945 struct params params = {0};
9946 char config_file[128] = {0};
9947
9948 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9949
9950 params.name = "enable_background_radar";
9951 params.value = enable?"1":"0";
9952 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
9953 wifi_hostapdWrite(config_file, &params, 1);
9954 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
9955
9956 /* TODO precac feature */
9957
9958 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9959 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009960}
9961
9962INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
9963{
developer58599c22022-09-13 16:40:34 +08009964 char config_file[128] = {0};
9965 char buf[64] = {0};
9966
9967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9968 if (NULL == enable || NULL == precac)
9969 return RETURN_ERR;
9970
9971 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
9972 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
9973 if (strncmp(enable, "1", 1) == 0)
9974 *enable = true;
9975 else
9976 *enable = false;
9977
9978 /* TODO precac feature */
9979
9980 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9981 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009982}
9983
9984INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
9985{
developer58599c22022-09-13 16:40:34 +08009986 *supported = TRUE;
9987 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009988}
9989
developer454b9462022-09-13 15:29:16 +08009990INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
9991{
9992 char cmd[128] = {0};
9993 char buf[64] = {0};
9994 char band_str[8] = {0};
9995 char GI[8] = {0};
9996 int tmp = 0;
9997 BOOL ax_mode = FALSE;
9998 BOOL short_GI = FALSE;
9999 FILE *f = NULL;
10000 wifi_band band;
10001
10002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10003
10004 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
10005 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10006 return RETURN_ERR;
10007 }
10008 if (strstr(buf, "ax") != NULL)
10009 ax_mode = TRUE;
10010
10011 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
10012 short_GI = TRUE;
10013 strcpy(GI, "0.4");
10014 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
10015 strcpy(GI, "1.6");
10016 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
10017 strcpy(GI, "3.2");
10018 else // default
10019 strcpy(GI, "0.8");
10020
10021 band = wifi_index_to_band(radio_index);
10022 if (band == band_2_4)
10023 strcpy(band_str, "2.4");
10024 else if (band == band_5)
10025 strcpy(band_str, "5");
10026 else if (band == band_6)
10027 strcpy(band_str, "6");
10028 else {
10029 wifi_dbg_printf("%s: invalid band\n");
10030 return RETURN_ERR;
10031 }
10032
10033 if (ax_mode == TRUE)
10034 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
10035 else
10036 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
10037 _syscmd(cmd, buf, sizeof(buf));
10038
10039 // Record GI for get GI function
10040 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10041 f = fopen(buf, "w");
10042 if (f != NULL) {
10043 fprintf(f, "%s", GI);
10044 }
10045 fclose(f);
10046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10047 return RETURN_OK;
10048}
10049
10050INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10051{
10052 char buf[32] = {0};
10053 char cmd[64] = {0};
10054
10055 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10056
10057 if (guard_interval == NULL)
10058 return RETURN_ERR;
10059
10060 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10061 _syscmd(cmd, buf, sizeof(buf));
10062
10063 if (strncmp(buf, "0.4", 3) == 0)
10064 *guard_interval = wifi_guard_interval_400;
10065 else if (strncmp(buf, "0.8", 3) == 0)
10066 *guard_interval = wifi_guard_interval_800;
10067 else if (strncmp(buf, "1.6", 3) == 0)
10068 *guard_interval = wifi_guard_interval_1600;
10069 else if (strncmp(buf, "3.2", 3) == 0)
10070 *guard_interval = wifi_guard_interval_3200;
10071 else
10072 *guard_interval = wifi_guard_interval_auto;
10073
10074 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10075 return RETURN_OK;
10076}
10077
developer3cc61d12022-09-13 16:36:05 +080010078INT wifi_setBSSColor(INT radio_index, UCHAR color)
10079{
10080 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10081 struct params params = {0};
10082 char config_file[128] = {0};
10083 char bss_color[4] ={0};
10084
10085 params.name = "he_bss_color";
10086 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10087 params.value = bss_color;
10088 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10089 wifi_hostapdWrite(config_file, &params, 1);
10090 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10091
10092 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10093 return RETURN_OK;
10094}
10095
10096INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10097{
10098 char config_file[128] = {0};
10099 char buf[64] = {0};
10100 char temp_output[128] = {'\0'};
10101
10102 wifi_dbg_printf("\nFunc=%s\n", __func__);
10103 if (NULL == color)
10104 return RETURN_ERR;
10105
10106 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10107 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10108
10109 if(strlen(buf) > 0) {
10110 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10111 } else {
10112 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10113 }
10114
10115 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10116 wifi_dbg_printf("\noutput_string=%s\n", color);
10117
10118 return RETURN_OK;
10119}
10120
developer06a01d92022-09-07 16:32:39 +080010121/* multi-psk support */
10122INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10123{
10124 char cmd[256];
10125
10126 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10127 AP_PREFIX,
10128 apIndex,
10129 mac[0],
10130 mac[1],
10131 mac[2],
10132 mac[3],
10133 mac[4],
10134 mac[5]
10135 );
10136 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10137 _syscmd(cmd, key->wifi_keyId, 64);
10138
10139
10140 return RETURN_OK;
10141}
10142
10143INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10144{
10145 FILE *fd = NULL;
10146 char fname[100];
10147 char cmd[128] = {0};
10148 char out[64] = {0};
10149 wifi_key_multi_psk_t * key = NULL;
10150 if(keysNumber < 0)
10151 return RETURN_ERR;
10152
10153 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10154 fd = fopen(fname, "w");
10155 if (!fd) {
10156 return RETURN_ERR;
10157 }
10158 key= (wifi_key_multi_psk_t *) keys;
10159 for(int i=0; i<keysNumber; ++i, key++) {
10160 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10161 }
10162 fclose(fd);
10163
10164 //reload file
10165 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10166 _syscmd(cmd, out, 64);
10167 return RETURN_OK;
10168}
10169
10170INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10171{
10172 FILE *fd = NULL;
10173 char fname[100];
10174 char * line = NULL;
10175 char * pos = NULL;
10176 size_t len = 0;
10177 ssize_t read = 0;
10178 INT ret = RETURN_OK;
10179 wifi_key_multi_psk_t *keys_it = NULL;
10180
10181 if (keysNumber < 1) {
10182 return RETURN_ERR;
10183 }
10184
10185 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10186 fd = fopen(fname, "r");
10187 if (!fd) {
10188 return RETURN_ERR;
10189 }
10190
10191 if (keys == NULL) {
10192 ret = RETURN_ERR;
10193 goto close;
10194 }
10195
10196 keys_it = keys;
10197 while ((read = getline(&line, &len, fd)) != -1) {
10198 //Strip trailing new line if present
10199 if (read > 0 && line[read-1] == '\n') {
10200 line[read-1] = '\0';
10201 }
10202
10203 if(strcmp(line,"keyid=")) {
10204 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10205 if (!(pos = index(line, ' '))) {
10206 ret = RETURN_ERR;
10207 goto close;
10208 }
10209 pos++;
10210 //Here should be 00:00:00:00:00:00
10211 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10212 printf("Not supported MAC: %s\n", pos);
10213 }
10214 if (!(pos = index(pos, ' '))) {
10215 ret = RETURN_ERR;
10216 goto close;
10217 }
10218 pos++;
10219
10220 //The rest is PSK
10221 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10222 keys_it++;
10223
10224 if(--keysNumber <= 0)
10225 break;
10226 }
10227 }
10228
10229close:
10230 free(line);
10231 fclose(fd);
10232 return ret;
10233}
10234/* end of multi-psk support */
10235
10236INT wifi_setNeighborReports(UINT apIndex,
10237 UINT numNeighborReports,
10238 wifi_NeighborReport_t *neighborReports)
10239{
10240 char cmd[256] = { 0 };
10241 char hex_bssid[13] = { 0 };
10242 char bssid[18] = { 0 };
10243 char nr[256] = { 0 };
10244 char ssid[256];
10245 char hex_ssid[256];
10246 INT ret;
10247
10248 /*rmeove all neighbors*/
10249 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10250 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);
10251 system(cmd);
10252
10253 for(unsigned int i = 0; i < numNeighborReports; i++)
10254 {
10255 memset(ssid, 0, sizeof(ssid));
10256 ret = wifi_getSSIDName(apIndex, ssid);
10257 if (ret != RETURN_OK)
10258 return RETURN_ERR;
10259
10260 memset(hex_ssid, 0, sizeof(hex_ssid));
10261 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10262 sprintf(hex_ssid + k,"%02x", ssid[j]);
10263
10264 snprintf(hex_bssid, sizeof(hex_bssid),
10265 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10266 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10267 snprintf(bssid, sizeof(bssid),
10268 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10269 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10270
10271 snprintf(nr, sizeof(nr),
10272 "%s" // bssid
10273 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10274 "%02hhx" // operclass
10275 "%02hhx" // channel
10276 "%02hhx", // phy_mode
10277 hex_bssid,
10278 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10279 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10280 neighborReports[i].opClass,
10281 neighborReports[i].channel,
10282 neighborReports[i].phyTable);
10283
10284 snprintf(cmd, sizeof(cmd),
10285 "hostapd_cli set_neighbor "
10286 "%s " // bssid
10287 "ssid=%s " // ssid
10288 "nr=%s " // nr
10289 "-i %s%d",
10290 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10291
10292 if (WEXITSTATUS(system(cmd)) != 0)
10293 {
10294 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10295 }
10296 }
10297
10298 return RETURN_OK;
10299}
10300
10301INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10302{
10303 return RETURN_OK;
10304}
10305
10306#ifdef _WIFI_HAL_TEST_
10307int main(int argc,char **argv)
10308{
10309 int index;
10310 INT ret=0;
10311 char buf[1024]="";
10312
10313 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10314 if(argc<3)
10315 {
10316 if(argc==2)
10317 {
10318 if(!strcmp(argv[1], "init"))
10319 return wifi_init();
10320 if(!strcmp(argv[1], "reset"))
10321 return wifi_reset();
10322 if(!strcmp(argv[1], "wifi_getHalVersion"))
10323 {
10324 char buffer[64];
10325 if(wifi_getHalVersion(buffer)==RETURN_OK)
10326 printf("Version: %s\n", buffer);
10327 else
10328 printf("Error in wifi_getHalVersion\n");
10329 return RETURN_OK;
10330 }
10331 }
10332 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10333 exit(-1);
10334 }
10335
10336 index = atoi(argv[2]);
10337 if(strstr(argv[1], "wifi_getApName")!=NULL)
10338 {
10339 wifi_getApName(index,buf);
10340 printf("Ap name is %s \n",buf);
10341 return 0;
10342 }
10343 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10344 {
10345 BOOL b = FALSE;
10346 BOOL *output_bool = &b;
10347 wifi_getRadioAutoChannelEnable(index,output_bool);
10348 printf("Channel enabled = %d \n",b);
10349 return 0;
10350 }
10351 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10352 {
10353 wifi_getApWpaEncryptionMode(index,buf);
10354 printf("encryption enabled = %s\n",buf);
10355 return 0;
10356 }
10357 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10358 {
10359 BOOL b = FALSE;
10360 BOOL *output_bool = &b;
10361 wifi_getApSsidAdvertisementEnable(index,output_bool);
10362 printf("advertisment enabled = %d\n",b);
10363 return 0;
10364 }
10365 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10366 {
10367 if(argc <= 3 )
10368 {
10369 printf("Insufficient arguments \n");
10370 exit(-1);
10371 }
10372
10373 char sta[20] = {'\0'};
10374 ULLONG handle= 0;
10375 strcpy(sta,argv[3]);
10376 mac_address_t st;
10377 mac_addr_aton(st,sta);
10378
10379 wifi_associated_dev_tid_stats_t tid_stats;
10380 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10381 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10382 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);
10383 }
10384
10385 if(strstr(argv[1], "getApEnable")!=NULL) {
10386 BOOL enable;
10387 ret=wifi_getApEnable(index, &enable);
10388 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10389 }
10390 else if(strstr(argv[1], "setApEnable")!=NULL) {
10391 BOOL enable = atoi(argv[3]);
10392 ret=wifi_setApEnable(index, enable);
10393 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10394 }
10395 else if(strstr(argv[1], "getApStatus")!=NULL) {
10396 char status[64];
10397 ret=wifi_getApStatus(index, status);
10398 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
10399 }
10400 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
10401 {
10402 wifi_getSSIDNameStatus(index,buf);
10403 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
10404 return 0;
10405 }
10406 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
10407 wifi_ssidTrafficStats2_t stats={0};
10408 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
10409 printf("%s %d: returns %d\n", argv[1], index, ret);
10410 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
10411 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
10412 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
10413 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
10414 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
10415 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
10416 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
10417 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
10418 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
10419 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
10420 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
10421 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
10422 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
10423 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
10424 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
10425 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
10426 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
10427 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
10428 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
10429 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
10430 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
10431 }
10432 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
10433 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
10434 UINT array_size=0;
10435 UINT i=0;
10436 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
10437 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10438 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
10439 printf(" neighbor %d:\n", i);
10440 printf(" ap_SSID =%s\n", pt->ap_SSID);
10441 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
10442 printf(" ap_Mode =%s\n", pt->ap_Mode);
10443 printf(" ap_Channel =%d\n", pt->ap_Channel);
10444 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
10445 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10446 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
10447 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
10448 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
10449 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
10450 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10451 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
10452 printf(" ap_Noise =%d\n", pt->ap_Noise);
10453 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
10454 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
10455 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
10456 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
10457 }
10458 if(neighbor_ap_array)
10459 free(neighbor_ap_array); //make sure to free the list
10460 }
10461 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
10462 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
10463 UINT array_size=0;
10464 UINT i=0;
10465 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
10466 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10467 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
10468 printf(" associated_dev %d:\n", i);
10469 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
10470 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
10471 printf(" cli_SNR =%d\n", pt->cli_SNR);
10472 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
10473 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
10474 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
10475 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
10476 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
10477 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
10478 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
10479 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
10480 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
10481 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
10482 }
10483 if(associated_dev_array)
10484 free(associated_dev_array); //make sure to free the list
10485 }
10486
10487 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
10488 {
10489#define MAX_ARRAY_SIZE 64
10490 int i, array_size;
10491 char *p, *ch_str;
10492 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
10493
10494 if(argc != 5)
10495 {
10496 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
10497 exit(-1);
10498 }
10499 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
10500
10501 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
10502 {
10503 strtok_r(ch_str, ",", &p);
10504 input_output_channelStats_array[i].ch_number = atoi(ch_str);
10505 }
10506 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
10507 if(!array_size)
10508 array_size=1;//Need to print current channel statistics
10509 for(i=0; i<array_size; i++)
10510 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
10511 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
10512 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
10513 input_output_channelStats_array[i].ch_number,\
10514 input_output_channelStats_array[i].ch_noise,\
10515 input_output_channelStats_array[i].ch_utilization_busy_rx,\
10516 input_output_channelStats_array[i].ch_utilization_busy_tx,\
10517 input_output_channelStats_array[i].ch_utilization_busy,\
10518 input_output_channelStats_array[i].ch_utilization_busy_ext,\
10519 input_output_channelStats_array[i].ch_utilization_total);
10520 }
10521
10522 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
10523 {
10524 if(argc <= 3 )
10525 {
10526 printf("Insufficient arguments \n");
10527 exit(-1);
10528 }
10529 char mac_addr[20] = {'\0'};
10530 wifi_device_t output_struct;
10531 int dev_index = atoi(argv[3]);
10532
10533 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
10534 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
10535 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);
10536 }
10537
10538 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
10539 {
10540 if (argc <= 3)
10541 {
10542 printf("Insufficient arguments\n");
10543 exit(-1);
10544 }
10545 char args[256];
10546 wifi_NeighborReport_t *neighborReports;
10547
10548 neighborReports = calloc(argc - 2, sizeof(neighborReports));
10549 if (!neighborReports)
10550 {
10551 printf("Failed to allocate memory");
10552 exit(-1);
10553 }
10554
10555 for (int i = 3; i < argc; ++i)
10556 {
10557 char *val;
10558 int j = 0;
10559 memset(args, 0, sizeof(args));
10560 strncpy(args, argv[i], sizeof(args));
10561 val = strtok(args, ";");
10562 while (val != NULL)
10563 {
10564 if (j == 0)
10565 {
10566 mac_addr_aton(neighborReports[i - 3].bssid, val);
10567 } else if (j == 1)
10568 {
10569 neighborReports[i - 3].info = strtol(val, NULL, 16);
10570 } else if (j == 2)
10571 {
10572 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
10573 } else if (j == 3)
10574 {
10575 neighborReports[i - 3].channel = strtol(val, NULL, 16);
10576 } else if (j == 4)
10577 {
10578 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
10579 } else {
10580 printf("Insufficient arguments]n\n");
10581 exit(-1);
10582 }
10583 val = strtok(NULL, ";");
10584 j++;
10585 }
10586 }
10587
10588 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
10589 if (ret != RETURN_OK)
10590 {
10591 printf("wifi_setNeighborReports ret = %d", ret);
10592 exit(-1);
10593 }
10594 }
10595 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
10596 {
10597 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
10598 printf("%s.\n", buf);
10599 else
10600 printf("Error returned\n");
10601 }
10602 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
10603 {
10604 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
10605 printf("%s.\n", buf);
10606 else
10607 printf("Error returned\n");
10608 }
10609 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
10610 {
10611 if (argc <= 2)
10612 {
10613 printf("Insufficient arguments\n");
10614 exit(-1);
10615 }
10616 char buf[64]= {'\0'};
10617 wifi_getRadioOperatingChannelBandwidth(index,buf);
10618 printf("Current bandwidth is %s \n",buf);
10619 return 0;
10620 }
10621 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
10622 {
10623 if (argc <= 5)
10624 {
10625 printf("Insufficient arguments\n");
10626 exit(-1);
10627 }
10628 UINT channel = atoi(argv[3]);
10629 UINT width = atoi(argv[4]);
10630 UINT beacon = atoi(argv[5]);
10631 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
10632 printf("Result = %d", ret);
10633 }
10634
10635 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10636 return 0;
10637}
10638
10639#endif
10640
10641#ifdef WIFI_HAL_VERSION_3
10642
developer1e5aa162022-09-13 16:06:24 +080010643INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
10644{
10645 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10646 if (bitMap & WIFI_BITRATE_1MBPS)
10647 strcat(BasicRate, "1,");
10648 if (bitMap & WIFI_BITRATE_2MBPS)
10649 strcat(BasicRate, "2,");
10650 if (bitMap & WIFI_BITRATE_5_5MBPS)
10651 strcat(BasicRate, "5.5,");
10652 if (bitMap & WIFI_BITRATE_6MBPS)
10653 strcat(BasicRate, "6,");
10654 if (bitMap & WIFI_BITRATE_9MBPS)
10655 strcat(BasicRate, "9,");
10656 if (bitMap & WIFI_BITRATE_11MBPS)
10657 strcat(BasicRate, "11,");
10658 if (bitMap & WIFI_BITRATE_12MBPS)
10659 strcat(BasicRate, "12,");
10660 if (bitMap & WIFI_BITRATE_18MBPS)
10661 strcat(BasicRate, "18,");
10662 if (bitMap & WIFI_BITRATE_24MBPS)
10663 strcat(BasicRate, "24,");
10664 if (bitMap & WIFI_BITRATE_36MBPS)
10665 strcat(BasicRate, "36,");
10666 if (bitMap & WIFI_BITRATE_48MBPS)
10667 strcat(BasicRate, "48,");
10668 if (bitMap & WIFI_BITRATE_54MBPS)
10669 strcat(BasicRate, "54,");
10670 if (strlen(BasicRate) != 0) // remove last comma
10671 BasicRate[strlen(BasicRate) - 1] = '\0';
10672 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10673 return RETURN_OK;
10674}
10675
10676INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
10677{
10678 UINT BitMap = 0;
10679 char *rate;
10680
10681 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10682 rate = strtok(BasicRatesList, ",");
10683 while(rate != NULL)
10684 {
10685 if (strcmp(rate, "1") == 0)
10686 BitMap |= WIFI_BITRATE_1MBPS;
10687 else if (strcmp(rate, "2") == 0)
10688 BitMap |= WIFI_BITRATE_2MBPS;
10689 else if (strcmp(rate, "5.5") == 0)
10690 BitMap |= WIFI_BITRATE_5_5MBPS;
10691 else if (strcmp(rate, "6") == 0)
10692 BitMap |= WIFI_BITRATE_6MBPS;
10693 else if (strcmp(rate, "9") == 0)
10694 BitMap |= WIFI_BITRATE_9MBPS;
10695 else if (strcmp(rate, "11") == 0)
10696 BitMap |= WIFI_BITRATE_11MBPS;
10697 else if (strcmp(rate, "12") == 0)
10698 BitMap |= WIFI_BITRATE_12MBPS;
10699 else if (strcmp(rate, "18") == 0)
10700 BitMap |= WIFI_BITRATE_18MBPS;
10701 else if (strcmp(rate, "24") == 0)
10702 BitMap |= WIFI_BITRATE_24MBPS;
10703 else if (strcmp(rate, "36") == 0)
10704 BitMap |= WIFI_BITRATE_36MBPS;
10705 else if (strcmp(rate, "48") == 0)
10706 BitMap |= WIFI_BITRATE_48MBPS;
10707 else if (strcmp(rate, "54") == 0)
10708 BitMap |= WIFI_BITRATE_54MBPS;
10709 rate = strtok(NULL, ",");
10710 }
10711 *basicRateBitMap = BitMap;
10712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10713 return RETURN_OK;
10714}
10715
10716// 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 +080010717INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
10718{
developer1e5aa162022-09-13 16:06:24 +080010719 char buf[128] = {0};
10720 char cmd[128] = {0};
10721 char config_file[64] = {0};
10722 int bandwidth;
10723 int set_mode;
10724 wifi_radio_operationParam_t current_param;
10725
10726 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10727
10728 multiple_set = TRUE;
10729 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
10730 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
10731 return RETURN_ERR;
10732 }
10733 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
10734 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
10735 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
10736 return RETURN_ERR;
10737 }
10738 }
10739 if (current_param.channelWidth != operationParam->channelWidth || (current_param.channel != operationParam->channel && !operationParam->autoChannelEnabled)) {
10740 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
10741 bandwidth = 20;
10742 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
10743 bandwidth = 40;
10744 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
10745 bandwidth = 80;
10746 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
10747 bandwidth = 160;
10748 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
10749 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
10750 return RETURN_ERR;
10751 }
10752 }
10753 if (current_param.variant != operationParam->variant) {
10754 // Two different definition bit map, so need to check every bit.
10755 if (operationParam->variant & WIFI_80211_VARIANT_A)
10756 set_mode |= WIFI_MODE_A;
10757 if (operationParam->variant & WIFI_80211_VARIANT_B)
10758 set_mode |= WIFI_MODE_B;
10759 if (operationParam->variant & WIFI_80211_VARIANT_G)
10760 set_mode |= WIFI_MODE_G;
10761 if (operationParam->variant & WIFI_80211_VARIANT_N)
10762 set_mode |= WIFI_MODE_N;
10763 if (operationParam->variant & WIFI_80211_VARIANT_AC)
10764 set_mode |= WIFI_MODE_AC;
10765 if (operationParam->variant & WIFI_80211_VARIANT_AX)
10766 set_mode |= WIFI_MODE_AX;
10767 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
10768 memset(buf, 0, sizeof(buf));
10769 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
10770 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
10771 return RETURN_ERR;
10772 }
10773 }
10774 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
10775 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
10776 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
10777 return RETURN_ERR;
10778 }
10779 }
10780 if (current_param.beaconInterval != operationParam->beaconInterval) {
10781 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
10782 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
10783 return RETURN_ERR;
10784 }
10785 }
10786 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
10787 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
10788 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
10789 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
10790 return RETURN_ERR;
10791 }
10792 }
10793 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
10794 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
10795 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
10796 return RETURN_ERR;
10797 }
10798 }
10799 if (current_param.guardInterval != operationParam->guardInterval) {
10800 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
10801 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
10802 return RETURN_ERR;
10803 }
10804 }
10805 if (current_param.transmitPower != operationParam->transmitPower) {
10806 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
10807 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
10808 return RETURN_ERR;
10809 }
10810 }
10811 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
10812 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
10813 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
10814 return RETURN_ERR;
10815 }
10816 }
10817 if (current_param.obssCoex != operationParam->obssCoex) {
10818 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
10819 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
10820 return RETURN_ERR;
10821 }
10822 }
10823 if (current_param.stbcEnable != operationParam->stbcEnable) {
10824 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
10825 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
10826 return RETURN_ERR;
10827 }
10828 }
10829 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
10830 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
10831 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
10832 return RETURN_ERR;
10833 }
10834 }
10835
10836 // if enable is true, then restart the radio
10837 wifi_setRadioEnable(index, FALSE);
10838 if (operationParam->enable == TRUE)
10839 wifi_setRadioEnable(index, TRUE);
10840 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10841
developer06a01d92022-09-07 16:32:39 +080010842 return RETURN_OK;
10843}
10844
10845INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
10846{
developer1e5aa162022-09-13 16:06:24 +080010847 char band[64] = {0};
10848 char buf[256] = {0};
10849 char config_file[64] = {0};
10850 char cmd[128] = {0};
10851 int ret = RETURN_ERR;
10852 int mode = 0;
10853 ULONG channel = 0;
10854 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080010855
10856 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10857 printf("Entering %s index = %d\n", __func__, (int)index);
10858
developer1e5aa162022-09-13 16:06:24 +080010859 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
10860 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
10861 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080010862 {
developer1e5aa162022-09-13 16:06:24 +080010863 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080010864 return RETURN_ERR;
10865 }
10866 operationParam->enable = enabled;
10867
10868 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080010869 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080010870 {
developer1e5aa162022-09-13 16:06:24 +080010871 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080010872 return RETURN_ERR;
10873 }
10874
10875 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080010876 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080010877 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080010878 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080010879 else if (!strcmp(band, "6GHz"))
10880 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080010881 else
10882 {
developer1e5aa162022-09-13 16:06:24 +080010883 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080010884 band);
10885 }
10886
developer1e5aa162022-09-13 16:06:24 +080010887 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
10888 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
10889 operationParam->channel = 0;
10890 operationParam->autoChannelEnabled = TRUE;
10891 } else {
10892 operationParam->channel = strtol(buf, NULL, 10);
10893 operationParam->autoChannelEnabled = FALSE;
10894 }
10895
developer06a01d92022-09-07 16:32:39 +080010896 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080010897 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
10898 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
10899 return RETURN_ERR;
10900 }
developer06a01d92022-09-07 16:32:39 +080010901 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
10902 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
10903 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer1e5aa162022-09-13 16:06:24 +080010904 else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
10905 else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080010906 else
10907 {
developer1e5aa162022-09-13 16:06:24 +080010908 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
10909 return false;
developer06a01d92022-09-07 16:32:39 +080010910 }
10911
developer1e5aa162022-09-13 16:06:24 +080010912 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
10913 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
10914 return RETURN_ERR;
10915 }
10916 // Two different definition bit map, so need to check every bit.
10917 if (mode & WIFI_MODE_A)
10918 operationParam->variant |= WIFI_80211_VARIANT_A;
10919 if (mode & WIFI_MODE_B)
10920 operationParam->variant |= WIFI_80211_VARIANT_B;
10921 if (mode & WIFI_MODE_G)
10922 operationParam->variant |= WIFI_80211_VARIANT_G;
10923 if (mode & WIFI_MODE_N)
10924 operationParam->variant |= WIFI_80211_VARIANT_N;
10925 if (mode & WIFI_MODE_AC)
10926 operationParam->variant |= WIFI_80211_VARIANT_AC;
10927 if (mode & WIFI_MODE_AX)
10928 operationParam->variant |= WIFI_80211_VARIANT_AX;
10929 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
10930 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
10931 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010932 }
developer1e5aa162022-09-13 16:06:24 +080010933 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
10934 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
10935 return RETURN_ERR;
10936 }
10937 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
10938 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
10939 return RETURN_ERR;
10940 }
developer06a01d92022-09-07 16:32:39 +080010941
developer1e5aa162022-09-13 16:06:24 +080010942 memset(buf, 0, sizeof(buf));
10943 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
10944 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
10945 return RETURN_ERR;
10946 }
10947 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
10948
10949 memset(buf, 0, sizeof(buf));
10950 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
10951 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
10952 return RETURN_ERR;
10953 }
10954 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
10955
10956 memset(buf, 0, sizeof(buf));
10957 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
10958 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
10959
10960 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
10961 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
10962 return RETURN_ERR;
10963 }
10964 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
10965 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
10966 return RETURN_ERR;
10967 }
10968
10969 memset(buf, 0, sizeof(buf));
10970 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
10971 if (strcmp(buf, "-1") == 0) {
10972 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
10973 operationParam->ctsProtection = FALSE;
10974 } else {
10975 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
10976 operationParam->ctsProtection = TRUE;
10977 }
10978
10979 memset(buf, 0, sizeof(buf));
10980 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
10981 if (strcmp(buf, "0") == 0)
10982 operationParam->obssCoex = FALSE;
10983 else
10984 operationParam->obssCoex = TRUE;
10985
10986 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
10987 _syscmd(cmd, buf, sizeof(buf));
10988 if (strlen(buf) != 0)
10989 operationParam->stbcEnable = TRUE;
10990 else
10991 operationParam->stbcEnable = FALSE;
10992
10993 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
10994 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
10995 return RETURN_ERR;
10996 }
10997
10998 // Below value is hardcoded
10999
11000 operationParam->numSecondaryChannels = 0;
11001 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11002 operationParam->channelSecondary[i] = 0;
11003 }
11004 operationParam->csa_beacon_count = 15;
11005 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011006
11007 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11008 return RETURN_OK;
11009}
11010
11011static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11012{
11013 if (radioIndex != 0 && radioIndex != 1)
11014 {
11015 printf("%s: Wrong radio index (%d)\n", __func__, index);
11016 return -1;
11017 }
11018
11019 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
11020 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
11021
11022 return (arrayIndex * 2) + radioIndex;
11023}
11024
11025INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11026{
11027 INT ret;
11028 int i;
11029 BOOL enabled = false;
11030 char buf[256];
11031 wifi_secur_list *secur_item;
11032 int vap_index;
11033 INT mode;
11034 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
11035
11036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11037 printf("Entering %s index = %d\n", __func__, (int)index);
11038
11039 map->vap_array[index].radio_index = index;
11040 for (i = 0; i < 5; i++)
11041 {
11042 vap_index = array_index_to_vap_index(index, i);
11043 if (vap_index < 0)
11044 {
11045 return RETURN_ERR;
11046 }
11047
11048 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
11049
11050 map->vap_array[i].vap_index = vap_index;
11051
11052 memset(buf, 0, sizeof(buf));
11053 wifi_getApName(vap_index, buf); // XXX: error handling
11054 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
11055
11056 ret = wifi_getSSIDEnable(vap_index, &enabled);
11057 if (ret != RETURN_OK)
11058 {
11059 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
11060 return RETURN_ERR;
11061 }
11062 map->vap_array[i].u.bss_info.enabled = enabled;
11063
11064 memset(buf, 0, sizeof(buf));
11065 wifi_getBaseBSSID(vap_index, buf);
11066 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11067 &map->vap_array[i].u.bss_info.bssid[0],
11068 &map->vap_array[i].u.bss_info.bssid[1],
11069 &map->vap_array[i].u.bss_info.bssid[2],
11070 &map->vap_array[i].u.bss_info.bssid[3],
11071 &map->vap_array[i].u.bss_info.bssid[4],
11072 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
11073
11074 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
11075 map->vap_array[i].u.bss_info.showSsid = enabled;
11076
11077 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
11078 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
11079 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
11080
11081 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11082 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
11083
11084 memset(buf, 0, sizeof(buf));
11085 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
11086 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
11087
11088 wifi_getApSecurityModeEnabled(vap_index, buf);
11089
11090 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
11091 {
11092 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
11093 return RETURN_ERR;
11094 }
11095 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
11096
11097 memset(buf, 0, sizeof(buf));
11098 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
11099 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);
11100
11101 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
11102 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
11103
11104 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
11105 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
11106
11107 wifi_getApIsolationEnable(vap_index, &enabled);
11108 map->vap_array[i].u.bss_info.isolation = enabled;
11109 }
11110 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11111 return RETURN_OK;
11112}
11113
11114INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11115{
11116 unsigned int i;
11117 wifi_vap_info_t *vap_info = NULL;
11118 int acl_mode;
11119 char *sec_str = NULL;
11120
11121 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11122 printf("Entering %s index = %d\n", __func__, (int)index);
11123 for (i = 0; i < map->num_vaps; i++)
11124 {
11125 vap_info = &map->vap_array[i];
11126 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11127
11128 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11129 else
11130 {
11131 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11132 else acl_mode = 1;
11133 }
11134 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11135 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11136 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11137
11138 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11139 if (sec_str)
11140 {
11141 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11142 }
11143 else
11144 {
11145 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11146 }
11147
11148 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11149 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11150
11151 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11152 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11153
11154 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11155
11156 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11157 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11158 }
11159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11160 return RETURN_OK;
11161}
11162
11163int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11164{
11165 char *token, *next;
11166 const char s[2] = ",";
11167 int count =0;
11168
11169 /* get the first token */
11170 token = strtok_r(pchannels, s, &next);
11171
11172 /* walk through other tokens */
11173 while( token != NULL && count < MAX_CHANNELS) {
11174 chlistptr->channels_list[count++] = atoi(token);
11175 token = strtok_r(NULL, s, &next);
11176 }
11177
11178 return count;
11179}
11180
11181static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11182{
11183 INT status;
11184 wifi_channels_list_t *chlistp;
11185 CHAR output_string[64];
11186 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011187 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011188
11189 if(rcap == NULL)
11190 {
11191 return RETURN_ERR;
11192 }
11193
11194 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011195 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011196
developer1e5aa162022-09-13 16:06:24 +080011197 if (band == band_2_4)
11198 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11199 else if (band == band_5)
11200 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11201 else if (band == band_6)
11202 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011203
11204 chlistp = &(rcap->channel_list[0]);
11205 memset(pchannels, 0, sizeof(pchannels));
11206
11207 /* possible number of radio channels */
11208 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11209 {
11210 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11211 }
11212 /* Number of channels and list*/
11213 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11214
11215 /* autoChannelSupported */
11216 /* always ON with wifi_getRadioAutoChannelSupported */
11217 rcap->autoChannelSupported = TRUE;
11218
11219 /* DCSSupported */
11220 /* always ON with wifi_getRadioDCSSupported */
11221 rcap->DCSSupported = TRUE;
11222
11223 /* zeroDFSSupported - TBD */
11224 rcap->zeroDFSSupported = FALSE;
11225
11226 /* Supported Country List*/
11227 memset(output_string, 0, sizeof(output_string));
11228 status = wifi_getRadioCountryCode(radioIndex, output_string);
11229 if( status != 0 ) {
11230 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11231 return RETURN_ERR;
11232 } else {
11233 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11234 }
11235 if(!strcmp(output_string,"US")){
11236 rcap->countrySupported[0] = wifi_countrycode_US;
11237 rcap->countrySupported[1] = wifi_countrycode_CA;
11238 } else if (!strcmp(output_string,"CA")) {
11239 rcap->countrySupported[0] = wifi_countrycode_CA;
11240 rcap->countrySupported[1] = wifi_countrycode_US;
11241 } else {
11242 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11243 }
11244
11245 rcap->numcountrySupported = 2;
11246
11247 /* csi */
11248 rcap->csi.maxDevices = 8;
11249 rcap->csi.soudingFrameSupported = TRUE;
11250
11251 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
11252
11253 /* channelWidth - all supported bandwidths */
11254 int i=0;
11255 rcap->channelWidth[i] = 0;
11256 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11257 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11258 WIFI_CHANNELBANDWIDTH_40MHZ);
11259
11260 }
developer1e5aa162022-09-13 16:06:24 +080011261 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080011262 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11263 WIFI_CHANNELBANDWIDTH_40MHZ |
11264 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
11265 }
11266
11267
11268 /* mode - all supported variants */
11269 // rcap->mode[i] = WIFI_80211_VARIANT_H;
11270 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011271 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 +080011272 }
11273 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011274 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
11275 }
11276 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
11277 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011278 }
11279 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
11280 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
11281
11282 /* supportedBitRate - all supported bitrates */
11283 rcap->supportedBitRate[i] = 0;
11284 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11285 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11286 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
11287 }
developer1e5aa162022-09-13 16:06:24 +080011288 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080011289 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11290 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
11291 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
11292 }
11293
11294
11295 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
11296 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
11297 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
11298 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
11299 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
11300 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
11301 rcap->cipherSupported = 0;
11302 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
11303 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
11304
11305 return RETURN_OK;
11306}
11307
11308INT wifi_getHalCapability(wifi_hal_capability_t *cap)
11309{
11310 INT status, radioIndex;
11311 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
11312 int iter = 0;
11313 unsigned int j;
11314 wifi_interface_name_idex_map_t *iface_info;
11315
11316 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11317
11318 memset(cap, 0, sizeof(wifi_hal_capability_t));
11319
11320 /* version */
11321 cap->version.major = WIFI_HAL_MAJOR_VERSION;
11322 cap->version.minor = WIFI_HAL_MINOR_VERSION;
11323
11324 /* number of radios platform property */
11325 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
11326 _syscmd(cmd, output, sizeof(output));
11327 cap->wifi_prop.numRadios = atoi(output);
11328
11329 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
11330 {
11331 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
11332 if (status != 0) {
11333 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
11334 return RETURN_ERR;
11335 }
11336
11337 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
11338 {
11339 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
11340 {
11341 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
11342 return RETURN_ERR;
11343 }
11344 iface_info = &cap->wifi_prop.interface_map[iter];
11345 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
11346 iface_info->rdk_radio_index = radioIndex;
11347 memset(output, 0, sizeof(output));
11348 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
11349 {
11350 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
11351 }
11352 // TODO: bridge name
11353 // TODO: vlan id
11354 // TODO: primary
11355 iface_info->index = array_index_to_vap_index(radioIndex, j);
11356 memset(output, 0, sizeof(output));
11357 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
11358 {
11359 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
11360 }
11361 iter++;
11362 }
11363 }
11364
11365 cap->BandSteeringSupported = FALSE;
11366 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11367 return RETURN_OK;
11368}
11369
11370INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
11371{
developer587c1b62022-09-27 15:58:59 +080011372 char buf[128] = {0};
11373 char config_file[128] = {0};
11374 char password[64] = {0};
11375 char mfp[32] = {0};
11376 char wpa_mode[32] = {0};
11377 struct params params = {0};
11378
11379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11380
11381 multiple_set = TRUE;
11382 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11383 if (security->mode == wifi_security_mode_none) {
11384 strcpy(wpa_mode, "None");
11385 } else if (security->mode == wifi_security_mode_wpa_personal)
11386 strcpy(wpa_mode, "WPA-Personal");
11387 else if (security->mode == wifi_security_mode_wpa2_personal)
11388 strcpy(wpa_mode, "WPA2-Personal");
11389 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
11390 strcpy(wpa_mode, "WPA-WPA2-Personal");
11391 else if (security->mode == wifi_security_mode_wpa_enterprise)
11392 strcpy(wpa_mode, "WPA-Enterprise");
11393 else if (security->mode == wifi_security_mode_wpa2_enterprise)
11394 strcpy(wpa_mode, "WPA2-Enterprise");
11395 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
11396 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
11397 else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
11398 strcpy(wpa_mode, "WPA3-Personal");
11399 else if (security->mode == wifi_security_mode_wpa3_enterprise)
11400 strcpy(wpa_mode, "WPA3-Enterprise");
11401
11402 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
11403
11404 strncpy(password, security->u.key.key, 63);
11405 password[63] = '\0';
11406 wifi_setApSecurityKeyPassphrase(ap_index, password);
11407
11408 if (security->mode != wifi_security_mode_none) {
11409 memset(&params, 0, sizeof(params));
11410 params.name = "wpa_pairwise";
11411 if (security->encr == wifi_encryption_tkip)
11412 params.value = "TKIP";
11413 else if (security->encr == wifi_encryption_aes)
11414 params.value = "CCMP";
11415 else if (security->encr == wifi_encryption_aes_tkip)
11416 params.value = "TKIP CCMP";
11417 wifi_hostapdWrite(config_file, &params, 1);
11418 }
11419
11420 if (security->mfp == wifi_mfp_cfg_disabled)
11421 strcpy(mfp, "Disable");
11422 else if (security->mfp == wifi_mfp_cfg_optional)
11423 strcpy(mfp, "Optional");
11424 else if (security->mfp == wifi_mfp_cfg_required)
11425 strcpy(mfp, "Required");
11426 wifi_setApSecurityMFPConfig(ap_index, mfp);
11427
11428 memset(&params, 0, sizeof(params));
11429 params.name = "transition_disable";
11430 if (security->wpa3_transition_disable == TRUE)
11431 params.value = "0x01";
11432 else
11433 params.value = "0x00";
11434 wifi_hostapdWrite(config_file, &params, 1);
11435
11436 memset(&params, 0, sizeof(params));
11437 params.name = "wpa_group_rekey";
11438 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
11439 params.value = buf;
11440 wifi_hostapdWrite(config_file, &params, 1);
11441
11442 memset(&params, 0, sizeof(params));
11443 params.name = "wpa_strict_rekey";
11444 params.value = security->strict_rekey?"1":"0";
11445 wifi_hostapdWrite(config_file, &params, 1);
11446
11447 memset(&params, 0, sizeof(params));
11448 params.name = "wpa_pairwise_update_count";
11449 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
11450 params.value = buf;
11451 wifi_hostapdWrite(config_file, &params, 1);
11452
11453 memset(&params, 0, sizeof(params));
11454 params.name = "disable_pmksa_caching";
11455 params.value = security->disable_pmksa_caching?"1":"0";
11456 wifi_hostapdWrite(config_file, &params, 1);
11457
11458 wifi_setApEnable(ap_index, FALSE);
11459 wifi_setApEnable(ap_index, TRUE);
11460
11461 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11462
developer06a01d92022-09-07 16:32:39 +080011463 return RETURN_OK;
11464}
11465
11466INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
11467{
developer587c1b62022-09-27 15:58:59 +080011468 char buf[128] = {0};
11469 char config_file[128] = {0};
11470 int disable = 0;
11471 // struct params params = {0};
11472
11473 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11474 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11475 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
11476 security->mode = wifi_security_mode_none;
11477 if (strlen(buf) != 0) {
11478 if (strcmp(buf, "WPA-Personal"))
11479 security->mode = wifi_security_mode_wpa_personal;
11480 else if (strcmp(buf, "WPA2-Personal"))
11481 security->mode = wifi_security_mode_wpa2_personal;
11482 else if (strcmp(buf, "WPA-WPA2-Personal"))
11483 security->mode = wifi_security_mode_wpa_wpa2_personal;
11484 else if (strcmp(buf, "WPA-Enterprise"))
11485 security->mode = wifi_security_mode_wpa_enterprise;
11486 else if (strcmp(buf, "WPA2-Enterprise"))
11487 security->mode = wifi_security_mode_wpa2_enterprise;
11488 else if (strcmp(buf, "WPA-WPA2-Enterprise"))
11489 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
11490 else if (strcmp(buf, "WPA3-Personal"))
11491 security->mode = wifi_security_mode_wpa3_personal;
11492 else if (strcmp(buf, "WPA3-Transition"))
11493 security->mode = wifi_security_mode_wpa3_transition;
11494 else if (strcmp(buf, "WPA3-Enterprise"))
11495 security->mode = wifi_security_mode_wpa3_enterprise;
11496 }
11497
11498 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
11499 if (security->mode == wifi_security_mode_none)
11500 security->encr = wifi_encryption_none;
11501 else {
11502 if (strcmp(buf, "TKIP") == 0)
11503 security->encr = wifi_encryption_tkip;
11504 else if (strcmp(buf, "CCMP") == 0)
11505 security->encr = wifi_encryption_aes;
11506 else
11507 security->encr = wifi_encryption_aes_tkip;
11508 }
11509
11510 memset(buf, 0, sizeof(buf));
11511 wifi_getApSecurityMFPConfig(ap_index, buf);
11512 if (strcmp(buf, "Disabled") == 0)
11513 security->mfp = wifi_mfp_cfg_disabled;
11514 else if (strcmp(buf, "Optional") == 0)
11515 security->mfp = wifi_mfp_cfg_optional;
11516 else if (strcmp(buf, "Required") == 0)
11517 security->mfp = wifi_mfp_cfg_required;
11518
11519 memset(buf, 0, sizeof(buf));
11520 security->wpa3_transition_disable = FALSE;
11521 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
11522 disable = strtol(buf, NULL, 16);
11523 if (disable != 0)
11524 security->wpa3_transition_disable = TRUE;
11525
11526 memset(buf, 0, sizeof(buf));
11527 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
11528 if (strlen(buf) == 0)
11529 security->rekey_interval = 86400;
11530 else
11531 security->rekey_interval = strtol(buf, NULL, 10);
11532
11533 memset(buf, 0, sizeof(buf));
11534 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
11535 if (strlen(buf) == 0)
11536 security->strict_rekey = 1;
11537 else
11538 security->strict_rekey = strtol(buf, NULL, 10);
11539
11540 memset(buf, 0, sizeof(buf));
11541 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
11542 if (strlen(buf) == 0)
11543 security->eapol_key_retries = 4;
11544 else
11545 security->eapol_key_retries = strtol(buf, NULL, 10);
11546
11547 memset(buf, 0, sizeof(buf));
11548 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
11549 if (strlen(buf) == 0)
11550 security->disable_pmksa_caching = FALSE;
11551 else
11552 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
11553
11554 /* TODO
11555 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
11556 */
11557 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
11558 security->eap_identity_req_timeout = 0;
11559 security->eap_identity_req_retries = 0;
11560 security->eap_req_timeout = 0;
11561 security->eap_req_retries = 0;
11562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080011563 return RETURN_OK;
11564}
11565
11566#endif /* WIFI_HAL_VERSION_3 */
11567
11568#ifdef WIFI_HAL_VERSION_3_PHASE2
11569INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
11570{
11571 return RETURN_OK;
11572}
11573#else
11574INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
11575{
11576 char cmd[128];
11577 BOOL status = false;
11578
11579 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
11580 return RETURN_ERR;
11581
11582 output_buf[0] = '\0';
11583
11584 wifi_getApEnable(ap_index,&status);
11585 if (!status)
11586 return RETURN_OK;
11587
11588 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
11589 _syscmd(cmd, output_buf, output_buf_size);
11590
11591 return RETURN_OK;
11592}
11593#endif
developer2f513ab2022-09-13 14:26:06 +080011594
11595INT wifi_getProxyArp(INT apIndex, BOOL *enable)
11596{
11597 char output[16]={'\0'};
11598 char config_file[MAX_BUF_SIZE] = {0};
11599
11600 if (!enable)
11601 return RETURN_ERR;
11602
11603 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
11604 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
11605
11606 if (strlen(output) == 0)
11607 *enable = FALSE;
11608 else if (strncmp(output, "1", 1) == 0)
11609 *enable = TRUE;
11610 else
11611 *enable = FALSE;
11612
11613 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
11614 return RETURN_OK;
11615}
developer2d9c30f2022-09-13 15:06:14 +080011616
11617INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
11618{
11619 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
11620 return RETURN_ERR;
11621 *output_enable=TRUE;
11622 return RETURN_OK;
11623}
developerfd7d2892022-09-13 16:44:53 +080011624
11625INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
11626{
11627 char cmd[128] = {0};
11628 char buf[128] = {0};
11629 char line[128] = {0};
11630 size_t len = 0;
11631 ssize_t read = 0;
11632 FILE *f = NULL;
11633 int index = 0;
11634 int exp = 0;
11635 int mantissa = 0;
11636 int duration = 0;
11637 int radio_index = 0;
11638 int max_radio_num = 0;
11639 uint twt_wake_interval = 0;
11640
11641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11642
11643 wifi_getMaxRadioNumber(&max_radio_num);
11644 radio_index = ap_index % max_radio_num;
11645 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
11646 _syscmd(cmd, buf, sizeof(buf));
11647 *numSessionReturned = strtol(buf, NULL, 10) - 1;
11648 if (*numSessionReturned > maxNumberSessions)
11649 *numSessionReturned = maxNumberSessions;
11650 else if (*numSessionReturned < 1) {
11651 *numSessionReturned = 0;
11652 return RETURN_OK;
11653 }
11654
11655 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
11656 if ((f = popen(cmd, "r")) == NULL) {
11657 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
11658 return RETURN_ERR;
11659 }
11660
11661 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
11662 while((read = fgets(line, sizeof(line), f)) != NULL) {
11663 char *tmp = NULL;
11664 strcpy(buf, line);
11665 tmp = strtok(buf, " ");
11666 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
11667 tmp = strtok(NULL, " ");
11668 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
11669 tmp = strtok(NULL, " ");
11670 if (strstr(tmp, "t")) {
11671 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
11672 }
11673 if (strstr(tmp, "a")) {
11674 twtSessions[index].twtParameters.operation.announced = TRUE;
11675 }
11676 tmp = strtok(NULL, " ");
11677 exp = strtol(tmp, NULL, 10);
11678 tmp = strtok(NULL, " ");
11679 mantissa = strtol(tmp, NULL, 10);
11680 tmp = strtok(NULL, " ");
11681 duration = strtol(tmp, NULL, 10);
11682
11683 // only implicit supported
11684 twtSessions[index].twtParameters.operation.implicit = TRUE;
11685 // only individual agreement supported
11686 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
11687
11688 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
11689 twt_wake_interval = mantissa * (1 << exp);
11690 if (twt_wake_interval/mantissa != (1 << exp)) {
11691 // Overflow handling
11692 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
11693 } else {
11694 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
11695 }
11696 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
11697 index++;
11698 }
11699
11700 pclose(f);
11701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11702 return RETURN_OK;
11703}