blob: edd8ea94696717fcc9f2ce8e626ccaad537ac0ce [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";
4872 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
4873 return RETURN_OK; //This is taken careof in beaconType
4874
4875 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4876 ret=wifi_hostapdWrite(config_file,&params,1);
4877 if(!ret)
4878 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
4879 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4880
4881 return ret;
4882}
4883
4884// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4885INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4886{
4887 //save to wifi config, and wait for wifi restart to apply
4888 char BeaconType[50] = {0};
4889 char config_file[MAX_BUF_SIZE] = {0};
4890
4891 *authMode = 0;
4892 wifi_getApBeaconType(apIndex,BeaconType);
4893 printf("%s____%s \n",__FUNCTION__,BeaconType);
4894
4895 if(strcmp(BeaconType,"None") == 0)
4896 strcpy(authMode,"None");
4897 else
4898 {
4899 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4900 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
4901 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
4902 if(strcmp(authMode,"WPA-PSK") == 0)
4903 strcpy(authMode,"SharedAuthentication");
4904 else if(strcmp(authMode,"WPA-EAP") == 0)
4905 strcpy(authMode,"EAPAuthentication");
4906 }
4907
4908 return RETURN_OK;
4909}
4910
4911// Outputs the number of stations associated per AP
4912INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
4913{
4914 char cmd[128]={0};
4915 char buf[128]={0};
4916 BOOL status = false;
4917
4918 if(apIndex > MAX_APS)
4919 return RETURN_ERR;
4920
4921 wifi_getApEnable(apIndex,&status);
4922 if (!status)
4923 return RETURN_OK;
4924
4925 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
4926 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
4927 _syscmd(cmd, buf, sizeof(buf));
4928 sscanf(buf,"%lu", output_ulong);
4929
4930 return RETURN_OK;
4931}
4932
4933// manually removes any active wi-fi association with the device specified on this ap
4934INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
4935{
4936 char buf[126]={'\0'};
4937
4938 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
4939 system(buf);
4940
4941 return RETURN_OK;
4942}
4943
4944// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
4945INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
4946{
4947 if(NULL == output_int)
4948 return RETURN_ERR;
4949 *output_int = apIndex%2;
4950 return RETURN_OK;
4951}
4952
4953// sets the radio index for the specific ap
4954INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
4955{
4956 //set to config only and wait for wifi reset to apply settings
4957 return RETURN_ERR;
4958}
4959
4960// Get the ACL MAC list per AP
4961INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4962{
4963 char cmd[MAX_CMD_SIZE]={'\0'};
4964 int ret = 0;
4965
4966 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4967 ret = _syscmd(cmd,macArray,buf_size);
4968 if (ret != 0)
4969 return RETURN_ERR;
4970
4971 return RETURN_OK;
4972}
4973
developere6aafda2022-09-13 14:59:28 +08004974INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4975{
4976 char cmd[MAX_CMD_SIZE]={'\0'};
4977 int ret = 0;
4978
4979 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4980 ret = _syscmd(cmd,macArray,buf_size);
4981 if (ret != 0)
4982 return RETURN_ERR;
4983
4984 return RETURN_OK;
4985}
4986
4987
developer06a01d92022-09-07 16:32:39 +08004988// Get the list of stations associated per AP
4989INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
4990{
4991 char cmd[128];
4992
4993 if(apIndex > 3) //Currently supporting apIndex upto 3
4994 return RETURN_ERR;
4995 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
4996 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
4997 _syscmd(cmd, macArray, buf_size);
4998
4999 return RETURN_OK;
5000}
5001
5002// adds the mac address to the filter list
5003//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5004INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5005{
5006 char cmd[MAX_CMD_SIZE]={'\0'};
5007 char buf[MAX_BUF_SIZE]={'\0'};
5008
5009#if 0
5010 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5011 if(_syscmd(cmd,buf,sizeof(buf)))
5012 return RETURN_ERR;
5013#endif
5014 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5015 if(_syscmd(cmd,buf,sizeof(buf)))
5016 return RETURN_ERR;
5017
5018 return RETURN_OK;
5019}
5020
5021// deletes the mac address from the filter list
5022//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5023INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5024{
5025 char cmd[MAX_CMD_SIZE]={'\0'};
5026 char buf[MAX_BUF_SIZE]={'\0'};
5027
5028#if 0
5029 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5030 if(_syscmd(cmd,buf,sizeof(buf)))
5031 return RETURN_ERR;
5032
5033#endif
5034 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5035 if(_syscmd(cmd,buf,sizeof(buf)))
5036 return RETURN_ERR;
5037
5038 return RETURN_OK;
5039}
5040
5041// outputs the number of devices in the filter list
5042INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5043{
developere6aafda2022-09-13 14:59:28 +08005044 char cmd[MAX_BUF_SIZE]={0};
5045 char buf[MAX_CMD_SIZE]={0};
5046
5047 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5048 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005049 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005050
5051 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5052 _syscmd(cmd, buf, sizeof(buf));
5053
5054 *output_uint = atoi(buf);
5055
5056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5057 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005058}
5059
5060INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5061{
5062 char cmd[128]={'\0'};
5063 char buf[128]={'\0'};
5064
5065 if(strcmp(action,"DENY")==0)
5066 {
5067 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5068 system(buf);
5069 return RETURN_OK;
5070 }
5071
5072 if(strcmp(action,"ALLOW")==0)
5073 {
5074 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5075 system(buf);
5076 return RETURN_OK;
5077 }
5078
5079 return RETURN_ERR;
5080
5081}
5082
5083// enable kick for devices on acl black list
5084INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5085{
5086 char aclArray[512] = {0}, *acl = NULL;
5087 char assocArray[512] = {0}, *asso = NULL;
5088
developere6aafda2022-09-13 14:59:28 +08005089 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005090 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5091
5092 // if there are no devices connected there is nothing to do
5093 if (strlen(assocArray) < 17)
5094 return RETURN_OK;
5095
5096 if (enable == TRUE)
5097 {
5098 //kick off the MAC which is in ACL array (deny list)
5099 acl = strtok(aclArray, "\r\n");
5100 while (acl != NULL) {
5101 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5102 wifi_kickApAssociatedDevice(apIndex, acl);
5103
5104 acl = strtok(NULL, "\r\n");
5105 }
developere6aafda2022-09-13 14:59:28 +08005106 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005107 }
5108 else
5109 {
developere6aafda2022-09-13 14:59:28 +08005110 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005111 }
5112
5113#if 0
5114 //TODO: need to revisit below implementation
5115 char aclArray[512]={0}, *acl=NULL;
5116 char assocArray[512]={0}, *asso=NULL;
5117 char buf[256]={'\0'};
5118 char action[10]={'\0'};
5119 FILE *fr=NULL;
5120 char interface[10]={'\0'};
5121 char config_file[MAX_BUF_SIZE] = {0};
5122
5123 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5124 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5125 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5126 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5127
5128 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5129 system(buf);
5130 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5131 system(buf);
5132 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5133 system(buf);
5134 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5135 system(buf);
5136 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5137 system(buf);
5138
5139 if ( enable == TRUE )
5140 {
5141 int device_count=0;
5142 strcpy(action,"DENY");
5143 //kick off the MAC which is in ACL array (deny list)
5144 acl = strtok (aclArray,",");
5145 while (acl != NULL) {
5146 if(strlen(acl)>=17)
5147 {
5148 apply_rules(apIndex, acl,action,interface);
5149 device_count++;
5150 //Register mac to be blocked ,in syscfg.db persistent storage
5151 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5152 system(buf);
5153 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5154 system(buf);
5155 system("syscfg commit");
5156
5157 wifi_kickApAssociatedDevice(apIndex, acl);
5158 }
5159 acl = strtok (NULL, ",");
5160 }
5161 }
5162 else
5163 {
5164 int device_count=0;
5165 char cmdmac[20]={'\0'};
5166 strcpy(action,"ALLOW");
5167 //kick off the MAC which is not in ACL array (allow list)
5168 acl = strtok (aclArray,",");
5169 while (acl != NULL) {
5170 if(strlen(acl)>=17)
5171 {
5172 apply_rules(apIndex, acl,action,interface);
5173 device_count++;
5174 //Register mac to be Allowed ,in syscfg.db persistent storage
5175 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5176 system(buf);
5177 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5178 system(buf);
5179 sprintf(cmdmac,"%s",acl);
5180 }
5181 acl = strtok (NULL, ",");
5182 }
5183 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5184 system(buf);
5185
5186 //Disconnect the mac which is not in ACL
5187 asso = strtok (assocArray,",");
5188 while (asso != NULL) {
5189 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5190 wifi_kickApAssociatedDevice(apIndex, asso);
5191 asso = strtok (NULL, ",");
5192 }
5193 }
5194#endif
5195 return RETURN_OK;
5196}
5197
5198INT wifi_setPreferPrivateConnection(BOOL enable)
5199{
5200 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5201 char buf[1024] = {0};
5202
5203 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5204 if(enable == TRUE)
5205 {
5206 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5207 sprintf(buf,"ifconfig %s down" ,interface_name);
5208 system(buf);
5209 memset(buf,0,sizeof(buf));
5210 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5211 sprintf(buf,"ifconfig %s down" ,interface_name);
5212 system(buf);
5213 }
5214 else
5215 {
5216 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5217 if(strcmp(ssid_cur_value,"1") == 0)
5218 wifi_RestartPrivateWifi_5G();
5219 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5220 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5221 if(strcmp(ssid_cur_value,"1") == 0)
5222 wifi_RestartHostapd_2G();
5223 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5224 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5225 if(strcmp(ssid_cur_value,"1") == 0)
5226 wifi_RestartHostapd_5G();
5227 }
5228 return RETURN_OK;
5229}
5230
5231// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5232INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5233{
5234 int items = 1;
5235 struct params list[2];
5236 char buf[MAX_BUF_SIZE] = {0};
5237 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005238 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005239
5240 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005241
developer10adcc12022-09-13 14:39:17 +08005242 if (filterMode == 0) {
5243 sprintf(buf, "%d", 0);
5244 list[0].value = buf;
5245
5246 char cmd[128], rtn[128];
5247 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5248 _syscmd(cmd, rtn, sizeof(rtn));
5249 memset(cmd,0,sizeof(cmd));
5250 // Delete deny_mac_file in hostapd configuration
5251 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5252 _syscmd(cmd, rtn, sizeof(rtn));
5253 }
5254 else if (filterMode == 1) {
5255 sprintf(buf, "%d", filterMode);
5256 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005257 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5258 list[1].name = "accept_mac_file";
5259 list[1].value = acl_file;
5260 items = 2;
developer10adcc12022-09-13 14:39:17 +08005261 } else if (filterMode == 2) {
5262 //TODO: deny_mac_file
5263 sprintf(buf, "%d", 0);
5264 list[0].value = buf;
5265 list[1].name = "deny_mac_file";
5266 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5267 list[1].value = deny_file;
5268 items = 2;
5269 } else {
5270 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005271 }
developer10adcc12022-09-13 14:39:17 +08005272
developer06a01d92022-09-07 16:32:39 +08005273 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5274 wifi_hostapdWrite(config_file, list, items);
5275
5276 return RETURN_OK;
5277
5278#if 0
5279 if(apIndex==0 || apIndex==1)
5280 {
5281 //set the filtermode
5282 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5283 system(buf);
5284 system("syscfg commit");
5285
5286 if(filterMode==0)
5287 {
5288 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5289 system(buf);
5290 return RETURN_OK;
5291 }
5292 }
5293 return RETURN_OK;
5294#endif
5295}
5296
5297// 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.
5298INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5299{
5300 return RETURN_ERR;
5301}
5302
5303// gets the vlan ID for this ap from an internal enviornment variable
5304INT wifi_getApVlanID(INT apIndex, INT *output_int)
5305{
5306 if(apIndex=0)
5307 {
5308 *output_int=100;
5309 return RETURN_OK;
5310 }
5311
5312 return RETURN_ERR;
5313}
5314
5315// sets the vlan ID for this ap to an internal enviornment variable
5316INT wifi_setApVlanID(INT apIndex, INT vlanId)
5317{
5318 //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)
5319 return RETURN_ERR;
5320}
5321
5322// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5323INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5324{
5325 snprintf(bridgeName, 32, "brlan0");
5326 snprintf(IP, 32, "10.0.0.1");
5327 snprintf(subnet, 32, "255.255.255.0");
5328
5329 return RETURN_OK;
5330}
5331
5332//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5333INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5334{
5335 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5336 return RETURN_ERR;
5337}
5338
5339// reset the vlan configuration for this ap
5340INT wifi_resetApVlanCfg(INT apIndex)
5341{
5342 //TODO: remove existing vlan for this ap
5343
5344 //Reapply vlan settings
5345 wifi_pushBridgeInfo(apIndex);
5346
5347 return RETURN_ERR;
5348}
5349
5350// 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.
5351INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5352{
5353 return RETURN_ERR;
5354}
5355
5356// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5357INT wifi_startHostApd()
5358{
5359 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5360 system("systemctl start hostapd.service");
5361 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5362 return RETURN_OK;
5363 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5364}
5365
5366// stops hostapd
5367INT wifi_stopHostApd()
5368{
5369 char cmd[128] = {0};
5370 char buf[128] = {0};
5371
5372 sprintf(cmd,"systemctl stop hostapd");
5373 _syscmd(cmd, buf, sizeof(buf));
5374
5375 return RETURN_OK;
5376}
5377
5378// restart hostapd dummy function
5379INT wifi_restartHostApd()
5380{
5381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5382 system("systemctl restart hostapd-global");
5383 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5384
5385 return RETURN_OK;
5386}
5387
5388static int align_hostapd_config(int index)
5389{
5390 ULONG lval;
5391 wifi_getRadioChannel(index%2, &lval);
5392 wifi_setRadioChannel(index%2, lval);
5393}
5394
5395// sets the AP enable status variable for the specified ap.
5396INT wifi_setApEnable(INT apIndex, BOOL enable)
5397{
5398 char config_file[MAX_BUF_SIZE] = {0};
5399 char cmd[MAX_CMD_SIZE] = {0};
5400 char buf[MAX_BUF_SIZE] = {0};
5401 BOOL status;
5402
5403 wifi_getApEnable(apIndex,&status);
5404 if (enable == status)
5405 return RETURN_OK;
5406
5407 if (enable == TRUE) {
5408 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5409 align_hostapd_config(apIndex);
5410 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5411 //Hostapd will bring up this interface
5412 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5413 _syscmd(cmd, buf, sizeof(buf));
5414 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5415 _syscmd(cmd, buf, sizeof(buf));
5416 }
5417 else {
5418 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5419 _syscmd(cmd, buf, sizeof(buf));
5420 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5421 _syscmd(cmd, buf, sizeof(buf));
5422 }
5423 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5424 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5425 _syscmd(cmd, buf, sizeof(buf));
5426 //Wait for wifi up/down to apply
5427 return RETURN_OK;
5428}
5429
5430// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5431INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5432{
5433 char cmd[MAX_CMD_SIZE] = {'\0'};
5434 char buf[MAX_BUF_SIZE] = {'\0'};
5435
5436 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5437 return RETURN_ERR;
5438
5439 *output_bool = 0;
5440
5441 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5442 {
developer70490032022-09-13 15:45:20 +08005443 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005444 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5445 }
5446
5447 return RETURN_OK;
5448}
5449
5450// Outputs the AP "Enabled" "Disabled" status from driver
5451INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5452{
5453 char cmd[128] = {0};
5454 char buf[128] = {0};
5455 BOOL output_bool;
5456
5457 if ( NULL == output_string)
5458 return RETURN_ERR;
5459 wifi_getApEnable(apIndex,&output_bool);
5460
5461 if(output_bool == 1)
5462 snprintf(output_string, 32, "Up");
5463 else
5464 snprintf(output_string, 32, "Disable");
5465
5466 return RETURN_OK;
5467}
5468
5469//Indicates whether or not beacons include the SSID name.
5470// outputs a 1 if SSID on the AP is enabled, else outputs 0
5471INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5472{
5473 //get the running status
5474 char config_file[MAX_BUF_SIZE] = {0};
5475 char buf[16] = {0};
5476
5477 if (!output)
5478 return RETURN_ERR;
5479
5480 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5481 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5482 *output = (strncmp("0",buf,1) == 0);
5483
5484 return RETURN_OK;
5485}
5486
5487// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5488INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5489{
5490 //store the config, apply instantly
5491 char config_file[MAX_BUF_SIZE] = {0};
5492 struct params list;
5493
5494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5495 list.name = "ignore_broadcast_ssid";
5496 list.value = enable?"0":"1";
5497
5498 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5499 wifi_hostapdWrite(config_file, &list, 1);
5500 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5501 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005502 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005503 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5504
5505 return RETURN_OK;
5506}
5507
5508//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5509INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5510{
5511 //get the running status
5512 if(!output_uint)
5513 return RETURN_ERR;
5514 *output_uint=16;
5515 return RETURN_OK;
5516}
5517
5518INT wifi_setApRetryLimit(INT apIndex, UINT number)
5519{
5520 //apply instantly
5521 return RETURN_ERR;
5522}
5523
5524//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5525INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5526{
5527 if(!output)
5528 return RETURN_ERR;
5529 *output=TRUE;
5530 return RETURN_OK;
5531}
5532
5533//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5534INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5535{
5536 //get the running status from driver
5537 if(!output)
5538 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005539
5540 char config_file[MAX_BUF_SIZE] = {0};
5541 char buf[16] = {0};
5542
5543 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5544 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
5545 if (strncmp("1",buf,1) == 0)
5546 *output = TRUE;
5547 else
5548 *output = FALSE;
5549
developer06a01d92022-09-07 16:32:39 +08005550 return RETURN_OK;
5551}
5552
5553//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5554INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5555{
5556 //get the running status from driver
5557 if(!output)
5558 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005559
5560 char config_file[MAX_BUF_SIZE] = {0};
5561 char buf[16] = {0};
5562
5563 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5564 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5565 if (strncmp("1",buf,1) == 0)
5566 *output = TRUE;
5567 else
5568 *output = FALSE;
5569
developer06a01d92022-09-07 16:32:39 +08005570 return RETURN_OK;
5571}
5572
5573// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5574INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5575{
5576 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005577 char config_file[MAX_BUF_SIZE] = {0};
5578 struct params list;
5579
5580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5581 list.name = "wmm_enabled";
5582 list.value = enable?"1":"0";
5583
5584 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5585 wifi_hostapdWrite(config_file, &list, 1);
5586 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5587 wifi_reloadAp(apIndex);
5588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5589
5590 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005591}
5592
5593//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.
5594INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5595{
5596 //get the running status from driver
5597 if(!output)
5598 return RETURN_ERR;
5599 *output=TRUE;
5600 return RETURN_OK;
5601}
5602
5603// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5604INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5605{
5606 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005607 char config_file[MAX_BUF_SIZE] = {0};
5608 struct params list;
5609
5610 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5611 list.name = "uapsd_advertisement_enabled";
5612 list.value = enable?"1":"0";
5613
5614 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5615 wifi_hostapdWrite(config_file, &list, 1);
5616 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5617 wifi_reloadAp(apIndex);
5618 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5619
5620 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005621}
5622
5623// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
5624INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5625{
5626 //save config and apply instantly.
5627 return RETURN_ERR;
5628}
5629
5630//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.
5631INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5632{
5633 //get the running status from driver
5634 if(!output_uint)
5635 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005636
5637 char output[16]={'\0'};
5638 char config_file[MAX_BUF_SIZE] = {0};
5639
5640 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5641 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5642 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5643 else {
5644 int device_num = atoi(output);
5645 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5646 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5647 return RETURN_ERR;
5648 }
5649 else {
5650 *output_uint = device_num;
5651 }
5652 }
5653
developer06a01d92022-09-07 16:32:39 +08005654 return RETURN_OK;
5655}
5656
5657INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5658{
5659 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005660 char str[MAX_BUF_SIZE]={'\0'};
5661 char cmd[MAX_CMD_SIZE]={'\0'};
5662 struct params params;
5663 char config_file[MAX_BUF_SIZE] = {0};
5664
5665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5666 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5667 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5668 return RETURN_ERR;
5669 }
5670 sprintf(str, "%d", number);
5671 params.name = "max_num_sta";
5672 params.value = str;
5673
5674 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5675 int ret = wifi_hostapdWrite(config_file, &params, 1);
5676 if (ret) {
5677 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5678 ,__func__, ret);
5679 }
5680
5681 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5682 if (ret) {
5683 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5684 ,__func__, ret);
5685 }
5686 wifi_reloadAp(apIndex);
5687 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5688
5689 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005690}
5691
5692//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.
5693INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5694{
5695 //get the current threshold
5696 if(!output_uint)
5697 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005698 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5699 if (*output_uint == 0)
5700 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08005701 return RETURN_OK;
5702}
5703
5704INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
5705{
5706 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08005707 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
5708 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005709 return RETURN_ERR;
5710}
5711
5712//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.
5713INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
5714{
5715 if(!output_uint)
5716 return RETURN_ERR;
5717 *output_uint = 3;
5718 return RETURN_OK;
5719}
5720
5721//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
5722INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
5723{
5724 if(!output_uint)
5725 return RETURN_ERR;
5726 *output_uint = 3;
5727 return RETURN_OK;
5728}
5729
5730//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.
5731INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
5732{
5733 if(!output_in_seconds)
5734 return RETURN_ERR;
5735 *output_in_seconds = 0;
5736 return RETURN_OK;
5737}
5738
5739//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
5740INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
5741{
5742 if(!output || apIndex>=MAX_APS)
5743 return RETURN_ERR;
5744 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
5745 snprintf(output, 128, "None,WPA2-Personal");
5746 return RETURN_OK;
5747}
5748
5749//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
5750INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
5751{
5752 char config_file[MAX_BUF_SIZE] = {0};
5753 char buf[32] = {0};
5754 if (!output)
5755 return RETURN_ERR;
5756
5757 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5758 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5759
5760 strcpy(output,"None");//Copying "None" to output string for default case
5761 if((strcmp(buf, "3")==0))
5762 snprintf(output, 32, "WPA-WPA2-Personal");
5763 else if((strcmp(buf, "2")==0))
5764 snprintf(output, 32, "WPA2-Personal");
5765 else if((strcmp(buf, "1")==0))
5766 snprintf(output, 32, "WPA-Personal");
5767 //TODO: need to handle enterprise authmode
5768
5769 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5770 return RETURN_OK;
5771#if 0
5772 //TODO: need to revisit below implementation
5773 char securityType[32], authMode[32];
5774 int enterpriseMode=0;
5775
5776 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5777 if(!output)
5778 return RETURN_ERR;
5779
5780 wifi_getApBeaconType(apIndex, securityType);
5781 strcpy(output,"None");//By default, copying "None" to output string
5782 if (strncmp(securityType,"None", strlen("None")) == 0)
5783 return RETURN_OK;
5784
5785 wifi_getApBasicAuthenticationMode(apIndex, authMode);
5786 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
5787
5788 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
5789 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
5790 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
5791 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
5792 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
5793 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
5794 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5795
5796 return RETURN_OK;
5797#endif
5798}
5799
5800INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
5801{
5802 char securityType[32];
5803 char authMode[32];
5804
5805 //store settings and wait for wifi up to apply
5806 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5807 if(!encMode)
5808 return RETURN_ERR;
5809
5810 printf("%s: apIndex %d, encMode %s\n",__func__, apIndex, encMode);
5811 if (strcmp(encMode, "None")==0)
5812 {
5813 strcpy(securityType,"None");
5814 strcpy(authMode,"None");
5815 }
5816 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
5817 {
5818 strcpy(securityType,"WPAand11i");
5819 strcpy(authMode,"PSKAuthentication");
5820 }
5821 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
5822 {
5823 strcpy(securityType,"WPAand11i");
5824 strcpy(authMode,"EAPAuthentication");
5825 }
5826 else if (strcmp(encMode, "WPA-Personal")==0)
5827 {
5828 strcpy(securityType,"WPA");
5829 strcpy(authMode,"PSKAuthentication");
5830 }
5831 else if (strcmp(encMode, "WPA-Enterprise")==0)
5832 {
5833 strcpy(securityType,"WPA");
5834 strcpy(authMode,"EAPAuthentication");
5835 }
5836 else if (strcmp(encMode, "WPA2-Personal")==0)
5837 {
5838 strcpy(securityType,"11i");
5839 strcpy(authMode,"PSKAuthentication");
5840 }
5841 else if (strcmp(encMode, "WPA2-Enterprise")==0)
5842 {
5843 strcpy(securityType,"11i");
5844 strcpy(authMode,"EAPAuthentication");
5845 }
5846 else
5847 {
5848 strcpy(securityType,"None");
5849 strcpy(authMode,"None");
5850 }
5851 wifi_setApBeaconType(apIndex, securityType);
5852 wifi_setApBasicAuthenticationMode(apIndex, authMode);
5853 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5854
5855 return RETURN_OK;
5856}
5857
5858
5859//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
5860// output_string must be pre-allocated as 64 character string by caller
5861// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5862INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
5863{
5864 char buf[16];
5865 char config_file[MAX_BUF_SIZE] = {0};
5866
5867 if(output_string==NULL)
5868 return RETURN_ERR;
5869
5870 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5871 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5872
5873 if(strcmp(buf,"0")==0)
5874 {
5875 printf("wpa_mode is %s ......... \n",buf);
5876 return RETURN_ERR;
5877 }
5878
5879 wifi_dbg_printf("\nFunc=%s\n",__func__);
5880 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5881 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5882 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5883
5884 return RETURN_OK;
5885}
5886
5887// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
5888// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5889INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
5890{
5891 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5892 struct params params={'\0'};
5893 int ret;
5894 char config_file[MAX_BUF_SIZE] = {0};
5895
5896 if(NULL == preSharedKey)
5897 return RETURN_ERR;
5898
5899 params.name = "wpa_passphrase";
5900
5901 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
5902 {
5903 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5904 return RETURN_ERR;
5905 }
5906 params.value = preSharedKey;
5907 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5908 ret = wifi_hostapdWrite(config_file, &params, 1);
5909 if(!ret)
5910 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5911 return ret;
5912 //TODO: call hostapd_cli for dynamic_config_control
5913}
5914
5915//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
5916// outputs the passphrase, maximum 63 characters
5917INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
5918{
5919 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
5920
5921 wifi_dbg_printf("\nFunc=%s\n",__func__);
5922 if (NULL == output_string)
5923 return RETURN_ERR;
5924
5925 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5926 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5927 if(strcmp(buf,"0")==0)
5928 {
5929 printf("wpa_mode is %s ......... \n",buf);
5930 return RETURN_ERR;
5931 }
5932
5933 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5934 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5935
5936 return RETURN_OK;
5937}
5938
5939// sets the passphrase enviornment variable, max 63 characters
5940INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
5941{
5942 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5943 struct params params={'\0'};
5944 char config_file[MAX_BUF_SIZE] = {0};
5945 int ret;
5946
5947 if(NULL == passPhrase)
5948 return RETURN_ERR;
5949
5950 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
5951 {
5952 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5953 return RETURN_ERR;
5954 }
5955 params.name = "wpa_passphrase";
5956 params.value = passPhrase;
5957 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5958 ret=wifi_hostapdWrite(config_file,&params,1);
5959 if(!ret)
5960 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5961
5962 return ret;
5963}
5964
5965//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.
5966INT wifi_setApSecurityReset(INT apIndex)
5967{
5968 //apply instantly
5969 return RETURN_ERR;
5970}
5971
5972//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).
5973INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
5974{
developer8f2ddd52022-09-13 15:39:24 +08005975 char config_file[64] = {0};
5976 char buf[64] = {0};
5977 char cmd[256] = {0};
5978
5979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5980
developer06a01d92022-09-07 16:32:39 +08005981 if(!IP_output || !Port_output || !RadiusSecret_output)
5982 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005983
developer8f2ddd52022-09-13 15:39:24 +08005984 // Read the first matched config
5985 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5986 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
5987 _syscmd(cmd, buf, sizeof(buf));
5988 strncpy(IP_output, buf, 64);
5989
5990 memset(buf, 0, sizeof(buf));
5991 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
5992 _syscmd(cmd, buf, sizeof(buf));
5993 *Port_output = atoi(buf);
5994
5995 memset(buf, 0, sizeof(buf));
5996 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
5997 _syscmd(cmd, buf, sizeof(buf));
5998 strncpy(RadiusSecret_output, buf, 64);
5999
6000 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006001 return RETURN_OK;
6002}
6003
6004INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6005{
developer8f2ddd52022-09-13 15:39:24 +08006006 char config_file[64] = {0};
6007 char port_str[8] = {0};
6008 char cmd[256] = {0};
6009 char buf[128] = {0};
6010
6011 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6012
6013 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6014
6015 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6016 _syscmd(cmd, buf, sizeof(buf));
6017 memset(cmd, 0, sizeof(cmd));
6018
6019 snprintf(port_str, sizeof(port_str), "%d", port);
6020 if (strlen(buf) == 0)
6021 // Append
6022 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6023 "auth_server_addr=%s\\n"
6024 "auth_server_port=%s\\n"
6025 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6026 else {
6027 // Delete the three lines setting after the "# radius 1" comment
6028 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6029 _syscmd(cmd, buf, sizeof(buf));
6030 memset(cmd, 0, sizeof(cmd));
6031 // Use "# radius 1" comment to find the location to insert the radius setting
6032 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6033 "# radius 1\\n"
6034 "auth_server_addr=%s\\n"
6035 "auth_server_port=%s\\n"
6036 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6037 }
6038 if(_syscmd(cmd, buf, sizeof(buf))) {
6039 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6040 return RETURN_ERR;
6041 }
6042
6043 wifi_reloadAp(apIndex);
6044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6045 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006046}
6047
6048INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6049{
developer8f2ddd52022-09-13 15:39:24 +08006050 char config_file[64] = {0};
6051 char buf[64] = {0};
6052 char cmd[256] = {0};
6053
6054 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6055
developer06a01d92022-09-07 16:32:39 +08006056 if(!IP_output || !Port_output || !RadiusSecret_output)
6057 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006058
6059 // Read the second matched config
6060 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6061 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6062 _syscmd(cmd, buf, sizeof(buf));
6063 strncpy(IP_output, buf, 64);
6064
6065 memset(buf, 0, sizeof(buf));
6066 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6067 _syscmd(cmd, buf, sizeof(buf));
6068 *Port_output = atoi(buf);
6069
6070 memset(buf, 0, sizeof(buf));
6071 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6072 _syscmd(cmd, buf, sizeof(buf));
6073 strncpy(RadiusSecret_output, buf, 64);
6074
6075 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006076 return RETURN_OK;
6077}
6078
6079INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6080{
developer8f2ddd52022-09-13 15:39:24 +08006081 char config_file[64] = {0};
6082 char port_str[8] = {0};
6083 char cmd[256] = {0};
6084 char buf[128] = {0};
6085
6086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6087
6088 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6089
6090 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6091 _syscmd(cmd, buf, sizeof(buf));
6092 memset(cmd, 0, sizeof(cmd));
6093
6094 snprintf(port_str, sizeof(port_str), "%d", port);
6095 if (strlen(buf) == 0)
6096 // Append
6097 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6098 "auth_server_addr=%s\\n"
6099 "auth_server_port=%s\\n"
6100 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6101 else {
6102 // Delete the three lines setting after the "# radius 2" comment
6103 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6104 _syscmd(cmd, buf, sizeof(buf));
6105 memset(cmd, 0, sizeof(cmd));
6106 // Use "# radius 2" comment to find the location to insert the radius setting
6107 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6108 "# radius 2\\n"
6109 "auth_server_addr=%s\\n"
6110 "auth_server_port=%s\\n"
6111 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6112 }
6113 if(_syscmd(cmd, buf, sizeof(buf))) {
6114 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6115 return RETURN_ERR;
6116 }
6117
6118 wifi_reloadAp(apIndex);
6119 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6120 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006121}
6122
6123//RadiusSettings
6124INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6125{
6126 if(!output)
6127 return RETURN_ERR;
6128
6129 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6130 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6131 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6132 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6133 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6134 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.
6135 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6136 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6137 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6138 //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.
6139
6140 return RETURN_OK;
6141}
6142
6143INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6144{
6145 //store the paramters, and apply instantly
6146 return RETURN_ERR;
6147}
6148
6149//Device.WiFi.AccessPoint.{i}.WPS.Enable
6150//Enables or disables WPS functionality for this access point.
6151// outputs the WPS enable state of this ap in output_bool
6152INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6153{
6154 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6155 if(!output_bool || !(apIndex==0 || apIndex==1))
6156 return RETURN_ERR;
6157 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6158 _syscmd(cmd, buf, sizeof(buf));
6159 if(strstr(buf, "configured"))
6160 *output_bool=TRUE;
6161 else
6162 *output_bool=FALSE;
6163
6164 return RETURN_OK;
6165}
6166
6167//Device.WiFi.AccessPoint.{i}.WPS.Enable
6168// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6169INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6170{
6171 char config_file[MAX_BUF_SIZE] = {0};
6172 struct params params;
6173
6174 if(!(apIndex==0 || apIndex==1))
6175 return RETURN_ERR;
6176 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6177 //store the paramters, and wait for wifi up to apply
6178 params.name = "wps_state";
6179 params.value = enable ? "2":"0";
6180
6181 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6182 wifi_hostapdWrite(config_file, &params, 1);
6183 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6184 wifi_reloadAp(apIndex);
6185
6186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6187 return RETURN_OK;
6188}
6189
6190//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
6191INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6192{
6193 if(!output)
6194 return RETURN_ERR;
6195 snprintf(output, 128, "PushButton,PIN");
6196 return RETURN_OK;
6197}
6198
6199//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6200//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.
6201// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6202INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6203{
6204 if(!output)
6205 return RETURN_ERR;
6206 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6207
6208 return RETURN_OK;
6209}
6210
6211//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6212// 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
6213INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6214{
6215 //apply instantly. No setting need to be stored.
6216 char methods[MAX_BUF_SIZE], *token, *next_token;
6217 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6218 struct params params;
6219
6220 if(!methodString || !(apIndex==0 || apIndex==1))
6221 return RETURN_ERR;
6222 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6223 //store the paramters, and wait for wifi up to apply
6224
6225 snprintf(methods, sizeof(methods), "%s", methodString);
6226 for(token=methods; *token; token=next_token)
6227 {
6228 strtok_r(token, ",", &next_token);
6229 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6230 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6231 else if(*token=='E')
6232 {
6233 if(!strcmp(methods, "Ethernet"))
6234 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6235 else if(!strcmp(methods, "ExternalNFCToken"))
6236 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6237 else
6238 printf("%s: Unknown WpsConfigMethod\n", __func__);
6239 }
6240 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6241 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6242 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6243 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6244 else if(*token=='P' )
6245 {
6246 if(!strcmp(token, "PushButton"))
6247 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6248 else if(!strcmp(token, "PIN"))
6249 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6250 else
6251 printf("%s: Unknown WpsConfigMethod\n", __func__);
6252 }
6253 else
6254 printf("%s: Unknown WpsConfigMethod\n", __func__);
6255 }
6256 params.name = "config_methods";
6257 params.value = config_methods;
6258 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6259 wifi_hostapdWrite(config_file, &params, 1);
6260 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6261 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6262
6263 return RETURN_OK;
6264}
6265
6266// outputs the pin value, ulong_pin must be allocated by the caller
6267INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6268{
6269 char buf[MAX_BUF_SIZE] = {0};
6270 char cmd[MAX_CMD_SIZE] = {0};
6271
6272 if(!output_ulong || !(apIndex==0 || apIndex==1))
6273 return RETURN_ERR;
6274 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6275 _syscmd(cmd, buf, sizeof(buf));
6276 if(strlen(buf) > 0)
6277 *output_ulong=strtoul(buf, NULL, 10);
6278
6279 return RETURN_OK;
6280}
6281
6282// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6283INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6284{
6285 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6286 char ap_pin[16] = {0};
6287 char buf[MAX_BUF_SIZE] = {0};
6288 char config_file[MAX_BUF_SIZE] = {0};
6289 ULONG prev_pin = 0;
6290 struct params params;
6291
6292 if(!(apIndex==0 || apIndex==1))
6293 return RETURN_ERR;
6294 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6295 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6296 params.name = "ap_pin";
6297 params.value = ap_pin;
6298 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6299 wifi_hostapdWrite(config_file, &params, 1);
6300 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6301 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6302
6303 return RETURN_OK;
6304}
6305
6306// Output string is either Not configured or Configured, max 32 characters
6307INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6308{
6309 char cmd[MAX_CMD_SIZE];
6310 char buf[MAX_BUF_SIZE]={0};
6311
6312 if(!output_string || !(apIndex==0 || apIndex==1))
6313 return RETURN_ERR;
6314 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6315 snprintf(output_string, 32, "Not configured");
6316 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6317 _syscmd(cmd, buf, sizeof(buf));
6318
developer348e3d92022-09-13 14:48:41 +08006319 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006320 snprintf(output_string, 32, "Configured");
6321 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6322
6323 return RETURN_OK;
6324}
6325
6326// sets the WPS pin for this AP
6327INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6328{
6329 char cmd[MAX_CMD_SIZE];
6330 char buf[MAX_BUF_SIZE]={0};
6331 BOOL enable;
6332
6333 if(!(apIndex==0 || apIndex==1))
6334 return RETURN_ERR;
6335 wifi_getApEnable(apIndex, &enable);
6336 if (!enable)
6337 return RETURN_ERR;
6338 wifi_getApWpsEnable(apIndex, &enable);
6339 if (!enable)
6340 return RETURN_ERR;
6341
6342 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6343 _syscmd(cmd, buf, sizeof(buf));
6344 if((strstr(buf, "OK"))!=NULL)
6345 return RETURN_OK;
6346
6347 return RETURN_ERR;
6348}
6349
6350// This function is called when the WPS push button has been pressed for this AP
6351INT wifi_setApWpsButtonPush(INT apIndex)
6352{
6353 char cmd[MAX_CMD_SIZE];
6354 char buf[MAX_BUF_SIZE]={0};
6355 BOOL enable=FALSE;
6356
6357 if(!(apIndex==0 || apIndex==1))
6358 return RETURN_ERR;
6359 wifi_getApEnable(apIndex, &enable);
6360 if (!enable)
6361 return RETURN_ERR;
6362
6363 wifi_getApWpsEnable(apIndex, &enable);
6364 if (!enable)
6365 return RETURN_ERR;
6366
6367 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6368 _syscmd(cmd, buf, sizeof(buf));
6369
6370 if((strstr(buf, "OK"))!=NULL)
6371 return RETURN_OK;
6372 return RETURN_ERR;
6373}
6374
6375// cancels WPS mode for this AP
6376INT wifi_cancelApWPS(INT apIndex)
6377{
6378 char cmd[MAX_CMD_SIZE];
6379 char buf[MAX_BUF_SIZE]={0};
6380
6381 if(!(apIndex==0 || apIndex==1))
6382 return RETURN_ERR;
6383 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6384 _syscmd(cmd,buf, sizeof(buf));
6385
6386 if((strstr(buf, "OK"))!=NULL)
6387 return RETURN_OK;
6388 return RETURN_ERR;
6389}
6390
6391//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6392//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6393INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6394{
6395 FILE *f;
6396 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6397 char cmd[256], buf[2048];
6398 char *param , *value, *line=NULL;
6399 size_t len = 0;
6400 ssize_t nread;
6401 wifi_associated_dev_t *dev=NULL;
6402
6403 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6404 *associated_dev_array = NULL;
6405 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6406 _syscmd(cmd,buf,sizeof(buf));
6407 *output_array_size = atoi(buf);
6408
6409 if (*output_array_size <= 0)
6410 return RETURN_OK;
6411
6412 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6413 *associated_dev_array = dev;
6414 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6415 _syscmd(cmd,buf,sizeof(buf));
6416 f = fopen("/tmp/connected_devices.txt", "r");
6417 if (f==NULL)
6418 {
6419 *output_array_size=0;
6420 return RETURN_ERR;
6421 }
6422 while ((nread = getline(&line, &len, f)) != -1)
6423 {
6424 param = strtok(line,"=");
6425 value = strtok(NULL,"=");
6426
6427 if( strcmp("flags",param) == 0 )
6428 {
6429 value[strlen(value)-1]='\0';
6430 if(strstr (value,"AUTHORIZED") != NULL )
6431 {
6432 dev[auth_temp].cli_AuthenticationState = 1;
6433 dev[auth_temp].cli_Active = 1;
6434 auth_temp++;
6435 read_flag=1;
6436 }
6437 }
6438 if(read_flag==1)
6439 {
6440 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6441 {
6442 value[strlen(value)-1]='\0';
6443 sscanf(value, "%x:%x:%x:%x:%x:%x",
6444 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6445 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6446 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6447 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6448 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6449 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6450 mac_temp++;
6451 read_flag=0;
6452 }
6453 }
6454 }
6455 *output_array_size = auth_temp;
6456 auth_temp=0;
6457 mac_temp=0;
6458 free(line);
6459 fclose(f);
6460 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6461 return RETURN_OK;
6462}
6463
6464#define MACADDRESS_SIZE 6
6465
6466INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6467{
6468 FILE *fp = NULL;
6469 char str[MAX_BUF_SIZE] = {0};
6470 int wificlientindex = 0 ;
6471 int count = 0;
6472 int signalstrength = 0;
6473 int arr[MACADDRESS_SIZE] = {0};
6474 unsigned char mac[MACADDRESS_SIZE] = {0};
6475 UINT wifi_count = 0;
6476 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6477 char pipeCmd[MAX_CMD_SIZE] = {0};
6478
6479 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6480 *output_array_size = 0;
6481 *associated_dev_array = NULL;
6482
6483 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6484 fp = popen(pipeCmd, "r");
6485 if (fp == NULL)
6486 {
6487 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6488 return RETURN_ERR;
6489 }
6490
6491 /* Read the output a line at a time - output it. */
6492 fgets(str, sizeof(str)-1, fp);
6493 wifi_count = (unsigned int) atoi ( str );
6494 *output_array_size = wifi_count;
6495 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6496 pclose(fp);
6497
6498 if(wifi_count == 0)
6499 {
6500 return RETURN_OK;
6501 }
6502 else
6503 {
6504 wifi_associated_dev3_t* temp = NULL;
6505 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6506 if(temp == NULL)
6507 {
6508 printf("Error Statement. Insufficient memory \n");
6509 return RETURN_ERR;
6510 }
6511
6512 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6513 system(pipeCmd);
6514 memset(pipeCmd,0,sizeof(pipeCmd));
6515 if(apIndex == 0)
6516 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6517 else if(apIndex == 1)
6518 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6519 system(pipeCmd);
6520
6521 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6522 if(fp == NULL)
6523 {
6524 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6525 return RETURN_ERR;
6526 }
6527 fclose(fp);
6528
6529 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6530 fp = popen(pipeCmd, "r");
6531 if(fp)
6532 {
6533 for(count =0 ; count < wifi_count; count++)
6534 {
6535 fgets(str, MAX_BUF_SIZE, fp);
6536 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6537 {
6538 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6539 {
6540 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6541
6542 }
6543 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6544 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]);
6545 }
6546 temp[count].cli_AuthenticationState = 1; //TODO
6547 temp[count].cli_Active = 1; //TODO
6548 }
6549 pclose(fp);
6550 }
6551
6552 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6553 fp = popen(pipeCmd, "r");
6554 if(fp)
6555 {
6556 pclose(fp);
6557 }
6558 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6559 if(fp)
6560 {
6561 for(count =0 ; count < wifi_count ;count++)
6562 {
6563 fgets(str, MAX_BUF_SIZE, fp);
6564 signalstrength = atoi(str);
6565 temp[count].cli_SignalStrength = signalstrength;
6566 temp[count].cli_RSSI = signalstrength;
6567 temp[count].cli_SNR = signalstrength + 95;
6568 }
6569 pclose(fp);
6570 }
6571
6572
6573 if((apIndex == 0) || (apIndex == 4))
6574 {
6575 for(count =0 ; count < wifi_count ;count++)
6576 {
6577 strcpy(temp[count].cli_OperatingStandard,"g");
6578 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6579 }
6580
6581 //BytesSent
6582 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6583 fp = popen(pipeCmd, "r");
6584 if(fp)
6585 {
6586 pclose(fp);
6587 }
6588 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6589 if(fp)
6590 {
6591 for (count = 0; count < wifi_count; count++)
6592 {
6593 fgets(str, MAX_BUF_SIZE, fp);
6594 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6595 }
6596 pclose(fp);
6597 }
6598
6599 //BytesReceived
6600 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6601 fp = popen(pipeCmd, "r");
6602 if (fp)
6603 {
6604 pclose(fp);
6605 }
6606 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6607 if (fp)
6608 {
6609 for (count = 0; count < wifi_count; count++)
6610 {
6611 fgets(str, MAX_BUF_SIZE, fp);
6612 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
6613 }
6614 pclose(fp);
6615 }
6616
6617 //PacketsSent
6618 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
6619 fp = popen(pipeCmd, "r");
6620 if (fp)
6621 {
6622 pclose(fp);
6623 }
6624
6625 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
6626 if (fp)
6627 {
6628 for (count = 0; count < wifi_count; count++)
6629 {
6630 fgets(str, MAX_BUF_SIZE, fp);
6631 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
6632 }
6633 pclose(fp);
6634 }
6635
6636 //PacketsReceived
6637 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
6638 fp = popen(pipeCmd, "r");
6639 if (fp)
6640 {
6641 pclose(fp);
6642 }
6643 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
6644 if (fp)
6645 {
6646 for (count = 0; count < wifi_count; count++)
6647 {
6648 fgets(str, MAX_BUF_SIZE, fp);
6649 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
6650 }
6651 pclose(fp);
6652 }
6653
6654 //ErrorsSent
6655 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6656 fp = popen(pipeCmd, "r");
6657 if (fp)
6658 {
6659 pclose(fp);
6660 }
6661 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6662 if (fp)
6663 {
6664 for (count = 0; count < wifi_count; count++)
6665 {
6666 fgets(str, MAX_BUF_SIZE, fp);
6667 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6668 }
6669 pclose(fp);
6670 }
6671
6672 //ErrorsSent
6673 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6674 fp = popen(pipeCmd, "r");
6675 if (fp)
6676 {
6677 pclose(fp);
6678 }
6679 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6680 if (fp)
6681 {
6682 for (count = 0; count < wifi_count; count++)
6683 {
6684 fgets(str, MAX_BUF_SIZE, fp);
6685 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6686 }
6687 pclose(fp);
6688 }
6689
6690 //LastDataDownlinkRate
6691 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
6692 fp = popen(pipeCmd, "r");
6693 if (fp)
6694 {
6695 pclose(fp);
6696 }
6697 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
6698 if (fp)
6699 {
6700 for (count = 0; count < wifi_count; count++)
6701 {
6702 fgets(str, MAX_BUF_SIZE, fp);
6703 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
6704 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
6705 }
6706 pclose(fp);
6707 }
6708
6709 //LastDataUplinkRate
6710 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
6711 fp = popen(pipeCmd, "r");
6712 if (fp)
6713 {
6714 pclose(fp);
6715 }
6716 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
6717 if (fp)
6718 {
6719 for (count = 0; count < wifi_count; count++)
6720 {
6721 fgets(str, MAX_BUF_SIZE, fp);
6722 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
6723 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
6724 }
6725 pclose(fp);
6726 }
6727
6728 }
6729 else if ((apIndex == 1) || (apIndex == 5))
6730 {
6731 for (count = 0; count < wifi_count; count++)
6732 {
6733 strcpy(temp[count].cli_OperatingStandard, "a");
6734 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
6735 temp[count].cli_BytesSent = 0;
6736 temp[count].cli_BytesReceived = 0;
6737 temp[count].cli_LastDataUplinkRate = 0;
6738 temp[count].cli_LastDataDownlinkRate = 0;
6739 temp[count].cli_PacketsSent = 0;
6740 temp[count].cli_PacketsReceived = 0;
6741 temp[count].cli_ErrorsSent = 0;
6742 }
6743 }
6744
6745 for (count = 0; count < wifi_count; count++)
6746 {
6747 temp[count].cli_Retransmissions = 0;
6748 temp[count].cli_DataFramesSentAck = 0;
6749 temp[count].cli_DataFramesSentNoAck = 0;
6750 temp[count].cli_MinRSSI = 0;
6751 temp[count].cli_MaxRSSI = 0;
6752 strncpy(temp[count].cli_InterferenceSources, "", 64);
6753 memset(temp[count].cli_IPAddress, 0, 64);
6754 temp[count].cli_RetransCount = 0;
6755 temp[count].cli_FailedRetransCount = 0;
6756 temp[count].cli_RetryCount = 0;
6757 temp[count].cli_MultipleRetryCount = 0;
6758 }
6759 *associated_dev_array = temp;
6760 }
6761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6762 return RETURN_OK;
6763}
6764
6765int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
6766{
6767 FILE *fp = NULL;
6768 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
6769 char cmd[MAX_CMD_SIZE];
6770 int count = 0;
6771
6772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6773 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
6774 fp = popen(cmd,"r");
6775 if(fp == NULL)
6776 {
6777 printf("Failed to run command in Function %s\n",__FUNCTION__);
6778 return 0;
6779 }
6780 if(fgets(path, sizeof(path)-1, fp) != NULL)
6781 {
6782 for(count=0;path[count]!='\n';count++)
6783 status[count]=path[count];
6784 status[count]='\0';
6785 }
6786 strcpy(wifi_status,status);
6787 pclose(fp);
6788 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6789 return RETURN_OK;
6790}
6791
6792/* #define HOSTAPD_STA_PARAM_ENTRIES 29
6793struct hostapd_sta_param {
6794 char key[50];
6795 char value[100];
6796}
6797
6798static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
6799 int i = 0;
6800
6801 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
6802 if (strncmp(params[i].key,key,50) == 0){
6803 return &params[i].value;
6804 }
6805 i++;
6806 }
6807 return NULL;
6808
6809} */
6810
6811static unsigned int count_occurences(const char *buf, const char *word)
6812{
6813 unsigned int n = 0;
6814 char *ptr = strstr(buf, word);
6815
6816 while (ptr++) {
6817 n++;
6818 ptr = strstr(ptr, word);
6819 }
6820
6821 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
6822 return n;
6823}
6824
6825static const char *get_line_from_str_buf(const char *buf, char *line)
6826{
6827 int i;
6828 int n = strlen(buf);
6829
6830 for (i = 0; i < n; i++) {
6831 line[i] = buf[i];
6832 if (buf[i] == '\n') {
6833 line[i] = '\0';
6834 return &buf[i + 1];
6835 }
6836 }
6837
6838 return NULL;
6839}
6840
6841INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6842{
6843 unsigned int assoc_cnt = 0;
6844 char interface_name[50] = {0};
6845 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
6846 char cmd[MAX_CMD_SIZE] = {'\0'};
6847 char line[256] = {'\0'};
6848 int i = 0;
6849 int ret = 0;
6850 const char *ptr = NULL;
6851 char *key = NULL;
6852 char *val = NULL;
6853 wifi_associated_dev3_t *temp = NULL;
6854 int rssi;
6855
6856 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6857
6858 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
6859 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
6860 return RETURN_ERR;
6861 }
6862
6863 // Example filtered output of 'iw dev' command:
6864 // Station 0a:69:72:10:d2:fa (on wifi0)
6865 // signal avg:-67 [-71, -71] dBm
6866 // Station 28:c2:1f:25:5f:99 (on wifi0)
6867 // signal avg:-67 [-71, -70] dBm
6868 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
6869 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
6870 return RETURN_ERR;
6871 }
6872
6873 ret = _syscmd(cmd, buf, sizeof(buf));
6874 if (ret == RETURN_ERR) {
6875 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
6876 return RETURN_ERR;
6877 }
6878
6879 *output_array_size = count_occurences(buf, "Station");
6880 if (*output_array_size == 0) return RETURN_OK;
6881
6882 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
6883 if (temp == NULL) {
6884 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
6885 return RETURN_ERR;
6886 }
6887 *associated_dev_array = temp;
6888
6889 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
6890 ptr = get_line_from_str_buf(buf, line);
6891 i = -1;
6892 while (ptr) {
6893 if (strstr(line, "Station")) {
6894 i++;
6895 key = strtok(line, " ");
6896 val = strtok(NULL, " ");
6897 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
6898 &temp[i].cli_MACAddress[0],
6899 &temp[i].cli_MACAddress[1],
6900 &temp[i].cli_MACAddress[2],
6901 &temp[i].cli_MACAddress[3],
6902 &temp[i].cli_MACAddress[4],
6903 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
6904 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
6905 free(*associated_dev_array);
6906 return RETURN_ERR;
6907 }
6908 }
6909 else if (i < 0) {
6910 ptr = get_line_from_str_buf(ptr, line);
6911 continue; // We didn't detect 'station' entry yet
6912 }
6913 else if (strstr(line, "signal avg")) {
6914 key = strtok(line, ":");
6915 val = strtok(NULL, " ");
6916 if (sscanf(val, "%d", &rssi) <= 0 ) {
6917 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
6918 free(*associated_dev_array);
6919 return RETURN_ERR;
6920 }
6921 temp[i].cli_RSSI = rssi;
6922 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
6923 }
6924 // Here other fields can be parsed if added to filter of 'iw dev' command
6925
6926 ptr = get_line_from_str_buf(ptr, line);
6927 };
6928
6929 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6930
6931 return RETURN_OK;
6932}
6933
6934#if 0
6935//To-do
6936INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6937{
6938 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6939
6940 //Using different approach to get required WiFi Parameters from system available commands
6941#if 0
6942 FILE *f;
6943 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6944 char cmd[256], buf[2048];
6945 char *param , *value, *line=NULL;
6946 size_t len = 0;
6947 ssize_t nread;
6948 wifi_associated_dev3_t *dev=NULL;
6949 *associated_dev_array = NULL;
6950 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6951 _syscmd(cmd,buf,sizeof(buf));
6952 *output_array_size = atoi(buf);
6953
6954 if (*output_array_size <= 0)
6955 return RETURN_OK;
6956
6957 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
6958 *associated_dev_array = dev;
6959 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
6960 _syscmd(cmd,buf,sizeof(buf));
6961 f = fopen("/tmp/connected_devices.txt", "r");
6962 if (f==NULL)
6963 {
6964 *output_array_size=0;
6965 return RETURN_ERR;
6966 }
6967 while ((nread = getline(&line, &len, f)) != -1)
6968 {
6969 param = strtok(line,"=");
6970 value = strtok(NULL,"=");
6971
6972 if( strcmp("flags",param) == 0 )
6973 {
6974 value[strlen(value)-1]='\0';
6975 if(strstr (value,"AUTHORIZED") != NULL )
6976 {
6977 dev[auth_temp].cli_AuthenticationState = 1;
6978 dev[auth_temp].cli_Active = 1;
6979 auth_temp++;
6980 read_flag=1;
6981 }
6982 }
6983 if(read_flag==1)
6984 {
6985 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6986 {
6987 value[strlen(value)-1]='\0';
6988 sscanf(value, "%x:%x:%x:%x:%x:%x",
6989 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6990 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6991 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6992 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6993 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6994 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6995
6996 }
6997 else if( strcmp("rx_packets",param) == 0 )
6998 {
6999 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7000 }
7001
7002 else if( strcmp("tx_packets",param) == 0 )
7003 {
7004 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7005 }
7006
7007 else if( strcmp("rx_bytes",param) == 0 )
7008 {
7009 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7010 }
7011
7012 else if( strcmp("tx_bytes",param) == 0 )
7013 {
7014 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7015 mac_temp++;
7016 read_flag=0;
7017 }
7018 }
7019 }
7020
7021 *output_array_size = auth_temp;
7022 auth_temp=0;
7023 mac_temp=0;
7024 free(line);
7025 fclose(f);
7026#endif
7027 char interface_name[MAX_BUF_SIZE] = {0};
7028 char wifi_status[MAX_BUF_SIZE] = {0};
7029 char hostapdconf[MAX_BUF_SIZE] = {0};
7030
7031 wifi_associated_dev3_t *dev_array = NULL;
7032 ULONG wifi_count = 0;
7033
7034 *associated_dev_array = NULL;
7035 *output_array_size = 0;
7036
7037 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7038 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7039 {
7040 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7041
7042 GetInterfaceName(interface_name, hostapdconf);
7043
7044 if(strlen(interface_name) > 1)
7045 {
7046 wifihal_interfacestatus(wifi_status,interface_name);
7047 if(strcmp(wifi_status,"RUNNING") == 0)
7048 {
7049 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7050
7051 *associated_dev_array = dev_array;
7052 *output_array_size = wifi_count;
7053 }
7054 else
7055 {
7056 *associated_dev_array = NULL;
7057 }
7058 }
7059 }
7060
7061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7062 return RETURN_OK;
7063}
7064#endif
7065
7066/* getIPAddress function */
7067/**
7068* @description Returning IpAddress of the Matched String
7069*
7070* @param
7071* @str Having MacAddress
7072* @ipaddr Having ipaddr
7073* @return The status of the operation
7074* @retval RETURN_OK if successful
7075* @retval RETURN_ERR if any error is detected
7076*
7077*/
7078
7079INT getIPAddress(char *str,char *ipaddr)
7080{
7081 FILE *fp = NULL;
7082 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7083 int LeaseTime = 0,ret = 0;
7084 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7085 {
7086 return RETURN_ERR;
7087 }
7088
7089 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7090 {
7091 /*
7092 Sample:sss
7093 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7094 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7095 */
7096 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7097 &(LeaseTime),
7098 phyAddr,
7099 ipAddr,
7100 hostName
7101 );
7102 if(ret != 4)
7103 continue;
7104 if(strcmp(str,phyAddr) == 0)
7105 strcpy(ipaddr,ipAddr);
7106 }
7107 return RETURN_OK;
7108}
7109
7110/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7111/**
7112* @description Returning Inactive wireless connected clients informations
7113*
7114* @param
7115* @filename Holding private_wifi 2g/5g content files
7116* @associated_dev_array Having inactiv wireless clients informations
7117* @output_array_size Returning Inactive wireless counts
7118* @return The status of the operation
7119* @retval RETURN_OK if successful
7120* @retval RETURN_ERR if any error is detected
7121*
7122*/
7123
7124INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7125{
7126 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7127 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7128 FILE *fp = NULL;
7129 int arr[MACADDRESS_SIZE] = {0};
7130 unsigned char mac[MACADDRESS_SIZE] = {0};
7131 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7132 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7133 fp = popen(buf,"r");
7134 if(fp == NULL)
7135 return RETURN_ERR;
7136 else
7137 {
7138 fgets(path,sizeof(path),fp);
7139 maccount = atoi(path);
7140 }
7141 pclose(fp);
7142 *output_array_size = maccount;
7143 wifi_associated_dev3_t* temp = NULL;
7144 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7145 *associated_dev_array = temp;
7146 if(temp == NULL)
7147 {
7148 printf("Error Statement. Insufficient memory \n");
7149 return RETURN_ERR;
7150 }
7151 memset(buf,0,sizeof(buf));
7152 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7153 fp = popen(buf,"r");
7154 for(count = 0; count < maccount ; count++)
7155 {
7156 fgets(path,sizeof(path),fp);
7157 for(i = 0; path[i]!='\n';i++)
7158 str[i]=path[i];
7159 str[i]='\0';
7160 getIPAddress(str,ipaddr);
7161 memset(buf,0,sizeof(buf));
7162 if(strlen(ipaddr) > 0)
7163 {
7164 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7165 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7166 {
7167 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7168 {
7169 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7170 {
7171 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7172
7173 }
7174 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7175 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]);
7176 }
7177 temp[count].cli_AuthenticationState = 0; //TODO
7178 temp[count].cli_Active = 0; //TODO
7179 temp[count].cli_SignalStrength = 0;
7180 }
7181 else //Active wireless clients info
7182 {
7183 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7184 {
7185 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7186 {
7187 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7188
7189 }
7190 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7191 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]);
7192 }
7193 temp[count].cli_Active = 1;
7194 }
7195 }
7196 memset(ipaddr,0,sizeof(ipaddr));
7197 }
7198 pclose(fp);
7199 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7200 return RETURN_OK;
7201}
7202//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7203//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7204//To get Band Steering Capability
7205INT wifi_getBandSteeringCapability(BOOL *support)
7206{
7207 *support = FALSE;
7208 return RETURN_OK;
7209}
7210
7211
7212//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7213//To get Band Steering enable status
7214INT wifi_getBandSteeringEnable(BOOL *enable)
7215{
7216 *enable = FALSE;
7217 return RETURN_OK;
7218}
7219
7220//To turn on/off Band steering
7221INT wifi_setBandSteeringEnable(BOOL enable)
7222{
7223 return RETURN_OK;
7224}
7225
7226//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7227//To get Band Steering AP group
7228INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7229{
7230 if (NULL == output_ApGroup)
7231 return RETURN_ERR;
7232
7233 strcpy(output_ApGroup, "1,2");
7234 return RETURN_OK;
7235}
7236
7237//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7238//to set and read the band steering BandUtilizationThreshold parameters
7239INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7240{
7241 return RETURN_ERR;
7242}
7243
7244INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7245{
7246 return RETURN_ERR;
7247}
7248
7249//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7250//to set and read the band steering RSSIThreshold parameters
7251INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7252{
7253 return RETURN_ERR;
7254}
7255
7256INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7257{
7258 return RETURN_ERR;
7259}
7260
7261
7262//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7263//to set and read the band steering physical modulation rate threshold parameters
7264INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7265{
7266 //If chip is not support, return -1
7267 return RETURN_ERR;
7268}
7269
7270INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7271{
7272 //If chip is not support, return -1
7273 return RETURN_ERR;
7274}
7275
7276//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7277//to set and read the inactivity time (in seconds) for steering under overload condition
7278INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7279{
7280 return RETURN_ERR;
7281}
7282
7283INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7284{
7285 return RETURN_ERR;
7286}
7287
7288//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7289//to set and read the inactivity time (in seconds) for steering under Idle condition
7290INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7291{
7292 return RETURN_ERR;
7293}
7294
7295INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7296{
7297 return RETURN_ERR;
7298}
7299
7300//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7301//pClientMAC[64]
7302//pSourceSSIDIndex[64]
7303//pDestSSIDIndex[64]
7304//pSteeringReason[256]
7305INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7306{
7307 //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
7308 *pSteeringTime=time(NULL);
7309 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7310 return RETURN_OK;
7311}
7312
7313INT wifi_ifConfigDown(INT apIndex)
7314{
7315 INT status = RETURN_OK;
7316 char cmd[64];
7317
7318 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7319 printf("%s: %s\n", __func__, cmd);
7320 system(cmd);
7321
7322 return status;
7323}
7324
7325INT wifi_ifConfigUp(INT apIndex)
7326{
7327 char cmd[128];
7328 char buf[1024];
7329
7330 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7331 _syscmd(cmd, buf, sizeof(buf));
7332 return 0;
7333}
7334
7335//>> Deprecated. Replace with wifi_applyRadioSettings
7336INT wifi_pushBridgeInfo(INT apIndex)
7337{
7338 char ip[32];
7339 char subnet[32];
7340 char bridge[32];
7341 int vlanId;
7342 char cmd[128];
7343 char buf[1024];
7344
7345 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7346 wifi_getApVlanID(apIndex,&vlanId);
7347
7348 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7349 _syscmd(cmd,buf, sizeof(buf));
7350
7351 return 0;
7352}
7353
7354INT wifi_pushChannel(INT radioIndex, UINT channel)
7355{
7356 char cmd[128];
7357 char buf[1024];
7358 int apIndex;
7359
7360 apIndex=(radioIndex==0)?0:1;
7361 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7362 _syscmd(cmd,buf, sizeof(buf));
7363
7364 return 0;
7365}
7366
7367INT wifi_pushChannelMode(INT radioIndex)
7368{
7369 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7370 return RETURN_ERR;
7371}
7372
7373INT wifi_pushDefaultValues(INT radioIndex)
7374{
7375 //Apply Comcast specified default radio settings instantly
7376 //AMPDU=1
7377 //AMPDUFrames=32
7378 //AMPDULim=50000
7379 //txqueuelen=1000
7380
7381 return RETURN_ERR;
7382}
7383
7384INT wifi_pushTxChainMask(INT radioIndex)
7385{
7386 //Apply default TxChainMask instantly
7387 return RETURN_ERR;
7388}
7389
7390INT wifi_pushRxChainMask(INT radioIndex)
7391{
7392 //Apply default RxChainMask instantly
7393 return RETURN_ERR;
7394}
7395
7396INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7397{
7398 INT status;
7399
7400 status = wifi_setSSIDName(apIndex,ssid);
7401 wifi_setApEnable(apIndex,FALSE);
7402 wifi_setApEnable(apIndex,TRUE);
7403
7404 return status;
7405}
7406
7407INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7408{
7409 //Apply default Ssid Advertisement instantly
7410 return RETURN_ERR;
7411}
7412
7413INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7414{
7415 INT status = RETURN_ERR;
7416 *output = 0;
7417 return RETURN_ERR;
7418}
7419
7420INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7421{
7422 return RETURN_OK;
7423}
7424
7425INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7426{
7427 return RETURN_OK;
7428}
7429
7430//To-do
7431INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7432{
developereb199ae2022-09-13 14:04:27 +08007433 char output[16]={'\0'};
7434 char config_file[MAX_BUF_SIZE] = {0};
7435
7436 if (!output_string)
7437 return RETURN_ERR;
7438
7439 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7440 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7441
7442 if (strlen(output) == 0)
7443 snprintf(output_string, 64, "Disabled");
7444 else if (strncmp(output, "0", 1) == 0)
7445 snprintf(output_string, 64, "Disabled");
7446 else if (strncmp(output, "1", 1) == 0)
7447 snprintf(output_string, 64, "Optional");
7448 else if (strncmp(output, "2", 1) == 0)
7449 snprintf(output_string, 64, "Required");
7450 else {
7451 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7452 return RETURN_ERR;
7453 }
7454
7455 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007456 return RETURN_OK;
7457}
7458INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7459{
developereb199ae2022-09-13 14:04:27 +08007460 char str[MAX_BUF_SIZE]={'\0'};
7461 char cmd[MAX_CMD_SIZE]={'\0'};
7462 struct params params;
7463 char config_file[MAX_BUF_SIZE] = {0};
7464
7465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7466 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7467 return RETURN_ERR;
7468
7469 params.name = "ieee80211w";
7470 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7471 params.value = "0";
7472 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7473 params.value = "1";
7474 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7475 params.value = "2";
7476 else{
7477 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7478 return RETURN_ERR;
7479 }
7480 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7481 wifi_hostapdWrite(config_file, &params, 1);
7482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007483 return RETURN_OK;
7484}
7485INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7486{
7487 char output[16]={'\0'};
7488 char config_file[MAX_BUF_SIZE] = {0};
7489
7490 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7491 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7492 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7493
7494 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7495 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7496
7497 return RETURN_OK;
7498}
7499
7500INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7501{
7502 return RETURN_OK;
7503}
7504
7505INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7506{
7507 return RETURN_OK;
7508}
7509
7510INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7511{
7512 return RETURN_OK;
7513}
7514
7515INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7516{
7517 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7518 char config_file[MAX_BUF_SIZE] = {0};
7519
7520 if (NULL == output)
7521 return RETURN_ERR;
7522 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7523 wifi_hostapdRead(config_file,"hw_mode",output,64);
7524
7525 if(strcmp(output,"b")==0)
7526 sprintf(output, "%s", "1,2,5.5,11");
7527 else if (strcmp(output,"a")==0)
7528 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7529 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7530 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7531
7532 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7533 return RETURN_OK;
7534}
7535
7536INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7537{
7538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7539 char *temp;
7540 char temp_output[128];
7541 char temp_TransmitRates[128];
7542 char config_file[MAX_BUF_SIZE] = {0};
7543
7544 if (NULL == output)
7545 return RETURN_ERR;
7546
7547 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7548 wifi_hostapdRead(config_file,"supported_rates",output,64);
7549
7550 strcpy(temp_TransmitRates,output);
7551 strcpy(temp_output,"");
7552 temp = strtok(temp_TransmitRates," ");
7553 while(temp!=NULL)
7554 {
7555 temp[strlen(temp)-1]=0;
7556 if((temp[0]=='5') && (temp[1]=='\0'))
7557 {
7558 temp="5.5";
7559 }
7560 strcat(temp_output,temp);
7561 temp = strtok(NULL," ");
7562 if(temp!=NULL)
7563 {
7564 strcat(temp_output,",");
7565 }
7566 }
7567 strcpy(output,temp_output);
7568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7569
7570 return RETURN_OK;
7571}
7572
7573INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7574{
7575 return RETURN_OK;
7576}
7577
7578
7579INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7580{
7581 int i=0;
7582 char *temp;
7583 char temp1[128];
7584 char temp_output[128];
7585 char temp_TransmitRates[128];
7586 struct params params={'\0'};
7587 char config_file[MAX_BUF_SIZE] = {0};
7588
7589 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7590 if(NULL == output)
7591 return RETURN_ERR;
7592
7593 strcpy(temp_TransmitRates,output);
7594
7595 for(i=0;i<strlen(temp_TransmitRates);i++)
7596 {
7597 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7598 {
7599 continue;
7600 }
7601 else
7602 {
7603 return RETURN_ERR;
7604 }
7605 }
7606 strcpy(temp_output,"");
7607 temp = strtok(temp_TransmitRates," ");
7608 while(temp!=NULL)
7609 {
7610 strcpy(temp1,temp);
7611 if(wlanIndex==1)
7612 {
7613 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
7614 {
7615 return RETURN_ERR;
7616 }
7617 }
7618
7619 if(strcmp(temp,"5.5")==0)
7620 {
7621 strcpy(temp1,"55");
7622 }
7623 else
7624 {
7625 strcat(temp1,"0");
7626 }
7627 strcat(temp_output,temp1);
7628 temp = strtok(NULL," ");
7629 if(temp!=NULL)
7630 {
7631 strcat(temp_output," ");
7632 }
7633 }
7634 strcpy(output,temp_output);
7635
7636
7637 params.name = "supported_rates";
7638 params.value = output;
7639
7640 wifi_dbg_printf("\n%s:",__func__);
7641 wifi_dbg_printf("params.value=%s\n",params.value);
7642 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7643 wifi_hostapdWrite(config_file,&params,1);
7644 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7645
7646 return RETURN_OK;
7647}
7648
7649
7650static char *sncopy(char *dst, int dst_sz, const char *src)
7651{
7652 if (src && dst && dst_sz > 0) {
7653 strncpy(dst, src, dst_sz);
7654 dst[dst_sz - 1] = '\0';
7655 }
7656 return dst;
7657}
7658
7659static int util_get_sec_chan_offset(int channel, const char* ht_mode)
7660{
7661 if (0 == strcmp(ht_mode, "HT40") ||
7662 0 == strcmp(ht_mode, "HT80") ||
7663 0 == strcmp(ht_mode, "HT160")) {
7664 switch (channel) {
7665 case 1 ... 7:
7666 case 36:
7667 case 44:
7668 case 52:
7669 case 60:
7670 case 100:
7671 case 108:
7672 case 116:
7673 case 124:
7674 case 132:
7675 case 140:
7676 case 149:
7677 case 157:
7678 return 1;
7679 case 8 ... 13:
7680 case 40:
7681 case 48:
7682 case 56:
7683 case 64:
7684 case 104:
7685 case 112:
7686 case 120:
7687 case 128:
7688 case 136:
7689 case 144:
7690 case 153:
7691 case 161:
7692 return -1;
7693 default:
7694 return -EINVAL;
7695 }
7696 }
7697
7698 return -EINVAL;
7699}
7700
7701static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
7702{
7703 if (NULL == hw_mode) return;
7704
7705 if (0 == strcmp(hw_mode, "ac"))
7706 sncopy(bw_mode, bw_mode_len, "ht vht");
7707
7708 if (0 == strcmp(hw_mode, "n"))
7709 sncopy(bw_mode, bw_mode_len, "ht");
7710
7711 return;
7712}
7713
7714static int util_chan_to_freq(int chan)
7715{
7716 if (chan == 14)
7717 return 2484;
7718 else if (chan < 14)
7719 return 2407 + chan * 5;
7720 else if (chan >= 182 && chan <= 196)
7721 return 4000 + chan * 5;
7722 else
7723 return 5000 + chan * 5;
7724 return 0;
7725}
7726
7727const int *util_unii_5g_chan2list(int chan, int width)
7728{
7729 static const int lists[] = {
7730 // <width>, <chan1>, <chan2>..., 0,
7731 20, 36, 0,
7732 20, 40, 0,
7733 20, 44, 0,
7734 20, 48, 0,
7735 20, 52, 0,
7736 20, 56, 0,
7737 20, 60, 0,
7738 20, 64, 0,
7739 20, 100, 0,
7740 20, 104, 0,
7741 20, 108, 0,
7742 20, 112, 0,
7743 20, 116, 0,
7744 20, 120, 0,
7745 20, 124, 0,
7746 20, 128, 0,
7747 20, 132, 0,
7748 20, 136, 0,
7749 20, 140, 0,
7750 20, 144, 0,
7751 20, 149, 0,
7752 20, 153, 0,
7753 20, 157, 0,
7754 20, 161, 0,
7755 20, 165, 0,
7756 40, 36, 40, 0,
7757 40, 44, 48, 0,
7758 40, 52, 56, 0,
7759 40, 60, 64, 0,
7760 40, 100, 104, 0,
7761 40, 108, 112, 0,
7762 40, 116, 120, 0,
7763 40, 124, 128, 0,
7764 40, 132, 136, 0,
7765 40, 140, 144, 0,
7766 40, 149, 153, 0,
7767 40, 157, 161, 0,
7768 80, 36, 40, 44, 48, 0,
7769 80, 52, 56, 60, 64, 0,
7770 80, 100, 104, 108, 112, 0,
7771 80, 116, 120, 124, 128, 0,
7772 80, 132, 136, 140, 144, 0,
7773 80, 149, 153, 157, 161, 0,
7774 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
7775 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
7776 -1 // final delimiter
7777 };
7778 const int *start;
7779 const int *p;
7780
7781 for (p = lists; *p != -1; p++) {
7782 if (*p == width) {
7783 for (start = ++p; *p != 0; p++) {
7784 if (*p == chan)
7785 return start;
7786 }
7787 }
7788 // move to the end of channel list of given width
7789 while (*p != 0) {
7790 p++;
7791 }
7792 }
7793
7794 return NULL;
7795}
7796
7797static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
7798{
7799 if (NULL == ht_mode)
7800 return 0;
7801
7802 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
7803 const int *chans = util_unii_5g_chan2list(channel, width);
7804 int sum = 0;
7805 int cnt = 0;
7806
7807 if (NULL == chans)
7808 return 0;
7809
7810 while (*chans) {
7811 sum += *chans;
7812 cnt++;
7813 chans++;
7814 }
7815 return sum / cnt;
7816}
7817
7818static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
7819{
7820 BOOL onlyG, onlyN, onlyA;
7821 CHAR tmp[64];
7822 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
7823 if (ret == RETURN_OK) {
7824 sncopy(hw_mode, hw_mode_size, tmp);
7825 }
7826 return ret;
7827}
7828
7829INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
7830{
7831 // Sample commands:
7832 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
7833 // hostapd_cli -i wifi0 chan_switch 30 2437
7834 char cmd[MAX_CMD_SIZE] = {0};
7835 char buf[MAX_BUF_SIZE] = {0};
7836 int freq = 0, ret = 0;
7837 char center_freq1_str[32] = ""; // center_freq1=%d
7838 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
7839 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
7840 char hw_mode[16] = ""; // n|ac
7841 char bw_mode[16] = ""; // ht|ht vht
7842 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
7843 int sec_chan_offset;
7844 int width;
7845
7846 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7847
7848 freq = util_chan_to_freq(channel);
7849
7850 // Get radio mode HT20|HT40|HT80 etc.
7851 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
7852 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
7853 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
7854 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
7855 if (sec_chan_offset != -EINVAL)
7856 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
7857
7858
7859 // Provide bandwith if specified
7860 if (channel_width_MHz > 20) {
7861 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
7862 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
7863 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
7864
7865 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
7866 }
7867
7868 int center_chan = 0;
7869 if (channel_width_MHz > 20) {
7870 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
7871 if (center_chan > 0) {
7872 int center_freq1 = util_chan_to_freq(center_chan);
7873 if (center_freq1)
7874 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
7875 }
7876 }
7877
7878 {
7879 // Only the first AP, other are hanging on the same radio
7880 int apIndex = radioIndex;
7881 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
7882 AP_PREFIX, apIndex, csa_beacon_count, freq,
7883 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
7884 wifi_dbg_printf("execute: '%s'\n", cmd);
7885 ret = _syscmd(cmd, buf, sizeof(buf));
7886 }
7887
7888 wifi_setRadioChannel(radioIndex, channel);
7889
7890 char *ext_str = "None";
7891 if (sec_chan_offset == 1) ext_str = "Above";
7892 else if (sec_chan_offset == -1) ext_str = "Below";
7893 wifi_setRadioExtChannel(radioIndex, ext_str);
7894
7895 wifi_setRadioCenterChannel(radioIndex, center_chan);
7896
7897 char mhz_str[16];
7898 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
7899 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
7900
7901 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7902
7903 return RETURN_OK;
7904}
7905
7906INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
7907{
7908 char cmd[1024] = {0};
7909 char buf[1024] = {0};
7910 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7911 wifi_neighbor_ap2_t *scan_array = NULL;
7912 int scan_count=0;
7913 int i =0;
7914 int freq=0;
7915 size_t len=0;
7916 FILE *f = NULL;
7917 ssize_t read = 0;
7918 char *line =NULL;
7919 char radio_ifname[64];
7920 char secondary_chan[64];
7921 int vht_channel_width = 0;
7922
7923 if(wifi_getRadioIfName(radio_index,radio_ifname)!=RETURN_OK)
7924 return RETURN_ERR;
7925
7926 /* sched_start is not supported on open source ath9k ath10k firmware
7927 * Using active scan as a workaround */
7928 sprintf(cmd,"iw dev %s scan |grep '^BSS\\|SSID:\\|freq:\\|signal:\\|HT operation:\\|secondary channel offset:\\|* channel width:'", radio_ifname);
7929 if((f = popen(cmd, "r")) == NULL) {
7930 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
7931 return RETURN_ERR;
7932 }
7933 read = getline(&line, &len, f);
7934 while (read != -1) {
7935 if(strncmp(line,"BSS",3) == 0) {
7936 i = scan_count;
7937 scan_count++;
7938 scan_array = realloc(scan_array,sizeof(wifi_neighbor_ap2_t)*scan_count);
7939 memset(&(scan_array[i]),0, sizeof(wifi_neighbor_ap2_t));
7940 sscanf(line,"BSS %17s", scan_array[i].ap_BSSID);
7941
7942 read = getline(&line, &len, f);
7943 sscanf(line," freq: %d", &freq);
7944 scan_array[i].ap_Channel = ieee80211_frequency_to_channel(freq);
7945
7946 read = getline(&line, &len, f);
7947 sscanf(line," signal: %d", &(scan_array[i].ap_SignalStrength));
7948
7949 read = getline(&line, &len, f);
7950 sscanf(line," SSID: %s", scan_array[i].ap_SSID);
7951 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);
7952 read = getline(&line, &len, f);
7953 if(strncmp(line,"BSS",3)==0) {
7954 // No HT and no VHT => 20Mhz
7955 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11%s", radio_index%1 ? "A": "G");
7956 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7957 continue;
7958 }
7959 if(strncmp(line," HT operation:",14)!= 0) {
7960 wifi_dbg_printf("HT output parsing error (%s)\n", line);
7961 goto output_error;
7962 }
7963
7964 read = getline(&line, &len, f);
7965 sscanf(line," * secondary channel offset: %s", &secondary_chan);
7966
7967 if(!strcmp(secondary_chan, "no")) {
7968 //20Mhz
7969 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
7970 }
7971
7972 if(!strcmp(secondary_chan, "above")) {
7973 //40Mhz +
7974 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
7975 }
7976
7977 if(!strcmp(secondary_chan, "below")) {
7978 //40Mhz -
7979 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
7980 }
7981
7982
7983 read = getline(&line, &len, f);
7984 if(strncmp(line," VHT operation:",15) !=0) {
7985 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7986 // No VHT
7987 continue;
7988 }
7989 read = getline(&line, &len, f);
7990 sscanf(line," * channel width: %d", &vht_channel_width);
7991 if(vht_channel_width == 1) {
7992 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT80");
7993 } else {
7994 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT40");
7995 }
7996
7997 }
7998 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7999 read = getline(&line, &len, f);
8000 }
8001 wifi_dbg_printf("%s:Counted BSS: %d\n",__func__, scan_count);
8002 *output_array_size = scan_count;
8003 *neighbor_ap_array = scan_array;
8004 free(line);
8005 pclose(f);
8006 return RETURN_OK;
8007
8008output_error:
8009 pclose(f);
8010 free(line);
8011 free(scan_array);
8012 return RETURN_ERR;
8013}
8014INT wifi_getApAssociatedDeviceStats(
8015 INT apIndex,
8016 mac_address_t *clientMacAddress,
8017 wifi_associated_dev_stats_t *associated_dev_stats,
8018 u64 *handle)
8019{
8020 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8021 char interface_name[50] = {0};
8022 char cmd[1024] = {0};
8023 char mac_str[18] = {0};
8024 char *key = NULL;
8025 char *val = NULL;
8026 FILE *f = NULL;
8027 char *line = NULL;
8028 size_t len = 0;
8029 ssize_t read = 0;
8030
8031 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8032 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8033 return RETURN_ERR;
8034 }
8035
8036 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8037 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8038 if((f = popen(cmd, "r")) == NULL) {
8039 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8040 return RETURN_ERR;
8041 }
8042
8043 while ((read = getline(&line, &len, f)) != -1) {
8044 key = strtok(line,":");
8045 val = strtok(NULL,":");
8046
8047 if(!strncmp(key,"rx bytes",8))
8048 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8049 if(!strncmp(key,"tx bytes",8))
8050 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8051 if(!strncmp(key,"rx packets",10))
8052 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8053 if(!strncmp(key,"tx packets",10))
8054 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8055 if(!strncmp(key,"tx retries",10))
8056 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8057 if(!strncmp(key,"tx failed",9))
8058 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8059 if(!strncmp(key,"rx drop misc",13))
8060 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8061 if(!strncmp(key,"rx bitrate",10)) {
8062 val = strtok(val, " ");
8063 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8064 }
8065 if(!strncmp(key,"tx bitrate",10)) {
8066 val = strtok(val, " ");
8067 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8068 }
8069 }
8070 free(line);
8071 pclose(f);
8072 return RETURN_OK;
8073}
8074
8075INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8076{
8077 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8078
8079 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8080 if (NULL == output_string)
8081 return RETURN_ERR;
8082
8083 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8084 _syscmd(cmd, buf, sizeof(buf));
8085
8086 //size of SSID name restricted to value less than 32 bytes
8087 snprintf(output_string, 32, "%s", buf);
8088 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8089
8090 return RETURN_OK;
8091}
8092
8093INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8094{
8095 //char cmd[MAX_CMD_SIZE] = {0};
8096 char config_file[MAX_BUF_SIZE] = {0};
8097 char buf[32] = {0};
8098
8099 if (!output_filterMode)
8100 return RETURN_ERR;
8101
8102 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8103 //_syscmd(cmd, buf, sizeof(buf));
8104 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8105 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008106 if(strlen(buf) == 0) {
8107 *output_filterMode = 0;
8108 }
8109 else {
8110 int macaddr_acl_mode = strtol(buf, NULL, 10);
8111 if (macaddr_acl_mode == 1) {
8112 *output_filterMode = 1;
8113 } else if (macaddr_acl_mode == 0) {
8114 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8115 if (strlen(buf) == 0) {
8116 *output_filterMode = 0;
8117 } else {
8118 *output_filterMode = 2;
8119 }
8120 } else {
8121 return RETURN_ERR;
8122 }
8123 }
developer06a01d92022-09-07 16:32:39 +08008124
8125 return RETURN_OK;
8126}
8127
8128INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8129{
8130 FILE *fp = NULL;
8131 char str[MAX_BUF_SIZE] = {0};
8132 int wificlientindex = 0 ;
8133 int count = 0;
8134 int signalstrength = 0;
8135 int arr[MACADDRESS_SIZE] = {0};
8136 unsigned char mac[MACADDRESS_SIZE] = {0};
8137 UINT wifi_count = 0;
8138 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8139 char pipeCmd[MAX_CMD_SIZE] = {0};
8140
8141 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8142 *output_array_size = 0;
8143 *associated_dev_array = NULL;
8144 char interface_name[50] = {0};
8145
8146 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8147 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8148 return RETURN_ERR;
8149 }
8150
8151 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8152 fp = popen(pipeCmd, "r");
8153 if (fp == NULL)
8154 {
8155 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8156 return RETURN_ERR;
8157 }
8158
8159 /* Read the output a line at a time - output it. */
8160 fgets(str, sizeof(str)-1, fp);
8161 wifi_count = (unsigned int) atoi ( str );
8162 *output_array_size = wifi_count;
8163 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8164 pclose(fp);
8165
8166 if(wifi_count == 0)
8167 {
8168 return RETURN_OK;
8169 }
8170 else
8171 {
8172 wifi_associated_dev2_t* temp = NULL;
8173 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8174 *associated_dev_array = temp;
8175 if(temp == NULL)
8176 {
8177 printf("Error Statement. Insufficient memory \n");
8178 return RETURN_ERR;
8179 }
8180
8181 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8182 system(pipeCmd);
8183
8184 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8185 if(fp == NULL)
8186 {
8187 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8188 return RETURN_ERR;
8189 }
8190 fclose(fp);
8191
8192 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8193 fp = popen(pipeCmd, "r");
8194 if(fp)
8195 {
8196 for(count =0 ; count < wifi_count; count++)
8197 {
8198 fgets(str, MAX_BUF_SIZE, fp);
8199 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8200 {
8201 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8202 {
8203 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8204
8205 }
8206 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8207 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]);
8208 }
8209 temp[count].cli_AuthenticationState = 1; //TODO
8210 temp[count].cli_Active = 1; //TODO
8211 }
8212 pclose(fp);
8213 }
8214
8215 //Updating RSSI per client
8216 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8217 fp = popen(pipeCmd, "r");
8218 if(fp)
8219 {
8220 pclose(fp);
8221 }
8222 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8223 if(fp)
8224 {
8225 for(count =0 ; count < wifi_count ;count++)
8226 {
8227 fgets(str, MAX_BUF_SIZE, fp);
8228 signalstrength = atoi(str);
8229 temp[count].cli_RSSI = signalstrength;
8230 }
8231 pclose(fp);
8232 }
8233
8234
8235 //LastDataDownlinkRate
8236 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8237 fp = popen(pipeCmd, "r");
8238 if (fp)
8239 {
8240 pclose(fp);
8241 }
8242 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8243 if (fp)
8244 {
8245 for (count = 0; count < wifi_count; count++)
8246 {
8247 fgets(str, MAX_BUF_SIZE, fp);
8248 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8249 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8250 }
8251 pclose(fp);
8252 }
8253
8254 //LastDataUplinkRate
8255 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8256 fp = popen(pipeCmd, "r");
8257 if (fp)
8258 {
8259 pclose(fp);
8260 }
8261 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8262 if (fp)
8263 {
8264 for (count = 0; count < wifi_count; count++)
8265 {
8266 fgets(str, MAX_BUF_SIZE, fp);
8267 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8268 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8269 }
8270 pclose(fp);
8271 }
8272 }
8273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8274 return RETURN_OK;
8275
8276}
8277
8278INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8279{
8280#if 0
8281 /*char buf[1024] = {0};
8282 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8283 _syscmd(cmd, buf, sizeof(buf));*/
8284
8285 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8286 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8287 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8288 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8289
8290 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.
8291 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].
8292 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].
8293 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].
8294 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8295 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8296
8297 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8298 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8299 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8300 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.
8301 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.
8302 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.
8303 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.
8304 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.
8305 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.
8306 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.
8307 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8308#endif
8309
8310 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008311 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008312 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008313 char pipeCmd[128] = {0};
8314 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008315 wifi_ssidTrafficStats2_t *out = output_struct;
8316
developerce736392022-09-13 15:24:34 +08008317 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008318 if (!output_struct)
8319 return RETURN_ERR;
8320
developerce736392022-09-13 15:24:34 +08008321 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8322 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8323 GetInterfaceName(interface_name, HConf_file);
8324 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008325
developer06a01d92022-09-07 16:32:39 +08008326 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008327 if (fp == NULL) {
8328 fprintf(stderr, "%s: popen failed\n", __func__);
8329 return RETURN_ERR;
8330 }
8331 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008332
developerce736392022-09-13 15:24:34 +08008333 if (strlen(str) == 0) // interface not exist
8334 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008335
developerce736392022-09-13 15:24:34 +08008336 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8337 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008338 pclose(fp);
8339
developerce736392022-09-13 15:24:34 +08008340 memset(str, 0, sizeof(str));
8341 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008342 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008343 if (fp == NULL) {
8344 fprintf(stderr, "%s: popen failed\n", __func__);
8345 return RETURN_ERR;
8346 }
8347 fgets(str, sizeof(str), fp);
8348
8349 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8350 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008351 pclose(fp);
developerce736392022-09-13 15:24:34 +08008352
8353 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8354 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8355
8356 // Not supported
8357 output_struct->ssid_RetransCount = 0;
8358 output_struct->ssid_FailedRetransCount = 0;
8359 output_struct->ssid_RetryCount = 0;
8360 output_struct->ssid_MultipleRetryCount = 0;
8361 output_struct->ssid_ACKFailureCount = 0;
8362 output_struct->ssid_AggregatedPacketCount = 0;
8363
developer06a01d92022-09-07 16:32:39 +08008364 return RETURN_OK;
8365}
8366
8367//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).
8368INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8369{
8370 char output_val[16]={'\0'};
8371 char config_file[MAX_BUF_SIZE] = {0};
8372
8373 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8374 if (!output)
8375 return RETURN_ERR;
8376 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8377 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8378
8379 if( strcmp(output_val,"1") == 0 )
8380 *output = TRUE;
8381 else
8382 *output = FALSE;
8383 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8384
8385 return RETURN_OK;
8386}
8387
8388INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8389{
8390 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8391 char str[MAX_BUF_SIZE]={'\0'};
8392 char string[MAX_BUF_SIZE]={'\0'};
8393 char cmd[MAX_CMD_SIZE]={'\0'};
8394 char *ch;
8395 char config_file[MAX_BUF_SIZE] = {0};
8396 struct params params;
8397
8398 if(enable == TRUE)
8399 strcpy(string,"1");
8400 else
8401 strcpy(string,"0");
8402
8403 params.name = "ap_isolate";
8404 params.value = string;
8405
8406 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8407 wifi_hostapdWrite(config_file,&params,1);
8408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8409
8410 return RETURN_OK;
8411}
8412
8413INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8414{
8415 if (NULL == output_dBm)
8416 return RETURN_ERR;
8417
8418 *output_dBm = 0;
8419 return RETURN_OK;
8420}
8421
8422INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8423{
8424 return RETURN_OK;
8425}
8426INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8427{
8428 return RETURN_OK;
8429}
8430INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8431{
8432 return RETURN_OK;
8433}
8434INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8435{
8436 return RETURN_OK;
8437}
8438INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8439{
8440 return RETURN_OK;
8441}
8442INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8443{
8444 char config_file[MAX_BUF_SIZE] = {0};
8445 struct params list;
8446
8447 list.name = "bss_transition";
8448 list.value = activate?"1":"0";
8449 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8450 wifi_hostapdWrite(config_file, &list, 1);
8451
8452 return RETURN_OK;
8453}
8454wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8455
8456void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8457{
8458 return;
8459}
8460
8461INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8462{
8463 // TODO Implement me!
8464 return RETURN_OK;
8465}
8466
8467INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8468{
developera3c68b92022-09-13 15:27:29 +08008469 char file_name[128] = {0};
8470 char buf[128] = {0};
8471 FILE *f = NULL;
8472
8473 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8474
8475 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8476 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8477 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8478 f = fopen(file_name, "w");
8479 if (f == NULL)
8480 return RETURN_ERR;
8481 // For mode == 0 is to disable filter, just don't write to the file.
8482 if (mode)
8483 fprintf(f, "%s", essid);
8484
8485 fclose(f);
8486 }
8487 } else { // special case, need to set AP's SSID as filter for each radio.
8488 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8489 f = fopen(file_name, "w");
8490 if (f == NULL)
8491 return RETURN_ERR;
8492
8493 // For mode == 0 is to disable filter, just don't write to the file.
8494 if (mode)
8495 fprintf(f, "%s", essid);
8496
8497 fclose(f);
8498 }
8499
8500 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008501 return RETURN_OK;
8502}
8503
8504INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
8505{
8506 // TODO Implement me!
8507 //Apply wifi_pushRadioChannel() instantly
8508 return RETURN_ERR;
8509}
8510
8511INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
8512{
8513 // TODO Implement me!
8514 return RETURN_OK;
8515}
8516
8517#ifdef HAL_NETLINK_IMPL
8518static int tidStats_callback(struct nl_msg *msg, void *arg) {
8519 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8520 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8521 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8522 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
8523 int rem , tid_index = 0;
8524
8525 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
8526 wifi_associated_dev_tid_entry_t *stats_entry;
8527
8528 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
8529 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
8530 };
8531 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
8532 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
8533 };
8534
8535 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8536 genlmsg_attrlen(gnlh, 0), NULL);
8537
8538
8539 if (!tb[NL80211_ATTR_STA_INFO]) {
8540 fprintf(stderr, "station stats missing!\n");
8541 return NL_SKIP;
8542 }
8543
8544 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
8545 tb[NL80211_ATTR_STA_INFO],
8546 stats_policy)) {
8547 fprintf(stderr, "failed to parse nested attributes!\n");
8548 return NL_SKIP;
8549 }
8550
8551 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
8552 {
8553 stats_entry = &out->tid_array[tid_index];
8554
8555 stats_entry->tid = tid_index;
8556 stats_entry->ac = _tid_ac_index_get[tid_index];
8557
8558 if(sinfo[NL80211_STA_INFO_TID_STATS])
8559 {
8560 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
8561 printf("failed to parse nested stats attributes!");
8562 return NL_SKIP;
8563 }
8564 }
8565 if(stats_info[NL80211_TID_STATS_TX_MSDU])
8566 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
8567
8568 if(tid_index < (PS_MAX_TID - 1))
8569 tid_index++;
8570 }
8571 //ToDo: sum_time_ms, ewma_time_ms
8572 return NL_SKIP;
8573}
8574#endif
8575
8576INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
8577{
8578#ifdef HAL_NETLINK_IMPL
8579 Netlink nl;
8580 char if_name[10];
8581
8582 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8583
8584 nl.id = initSock80211(&nl);
8585
8586 if (nl.id < 0) {
8587 fprintf(stderr, "Error initializing netlink \n");
8588 return -1;
8589 }
8590
8591 struct nl_msg* msg = nlmsg_alloc();
8592
8593 if (!msg) {
8594 fprintf(stderr, "Failed to allocate netlink message.\n");
8595 nlfree(&nl);
8596 return -2;
8597 }
8598
8599 genlmsg_put(msg,
8600 NL_AUTO_PORT,
8601 NL_AUTO_SEQ,
8602 nl.id,
8603 0,
8604 0,
8605 NL80211_CMD_GET_STATION,
8606 0);
8607
8608 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
8609 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8610 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
8611 nl_send_auto(nl.socket, msg);
8612 nl_recvmsgs(nl.socket, nl.cb);
8613 nlmsg_free(msg);
8614 nlfree(&nl);
8615 return RETURN_OK;
8616#else
8617//iw implementation
8618#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
8619#define TOTAL_MAX_LINES 50
8620
8621 char buf[256] = {'\0'}; /* or other suitable maximum line size */
8622 char if_name[10];
8623 FILE *fp=NULL;
8624 char pipeCmd[1024]= {'\0'};
8625 int lines,tid_index=0;
8626 char mac_addr[20] = {'\0'};
8627
8628 wifi_associated_dev_tid_entry_t *stats_entry;
8629
8630 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8631 strcpy(mac_addr,clientMacAddress);
8632
8633 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
8634 fp= popen(pipeCmd,"r");
8635 if(fp == NULL)
8636 {
8637 perror("popen for station dump failed\n");
8638 return RETURN_ERR;
8639 }
8640 pclose(fp);
8641
8642 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
8643 fp=popen(pipeCmd,"r");
8644 if(fp == NULL)
8645 {
8646 perror("popen for grep station failed\n");
8647 return RETURN_ERR;
8648 }
8649 else if(fgets(buf,sizeof(buf),fp) != NULL)
8650 lines=atoi(buf);
8651 else
8652 {
8653 pclose(fp);
8654 fprintf(stderr,"No devices are connected \n");
8655 return RETURN_ERR;
8656 }
8657 pclose(fp);
8658
8659 if(lines == 1)
8660 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
8661
8662 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
8663 {
8664 stats_entry = &tid_stats->tid_array[tid_index];
8665 stats_entry->tid = tid_index;
8666
8667 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);
8668
8669 fp=popen(pipeCmd,"r");
8670 if(fp ==NULL)
8671 {
8672 perror("Failed to read from tid file \n");
8673 return RETURN_ERR;
8674 }
8675 else if(fgets(buf,sizeof(buf),fp) != NULL)
8676 stats_entry->num_msdus = atol(buf);
8677
8678 pclose(fp);
8679 stats_entry->ac = _tid_ac_index_get[tid_index];
8680// TODO:
8681// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
8682// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
8683 }
8684 return RETURN_OK;
8685#endif
8686}
8687
8688
8689INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
8690{
8691 // TODO Implement me!
8692 return RETURN_OK;
8693}
8694
8695
8696INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
8697{
8698 // TODO Implement me!
8699 return RETURN_ERR;
8700}
8701
8702INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
8703{
8704 // TODO Implement me!
8705 return RETURN_ERR;
8706}
8707
8708INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
8709{
8710 // TODO Implement me!
8711 return RETURN_ERR;
8712}
8713
8714INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
8715{
8716 // TODO Implement me!
8717 return RETURN_ERR;
8718}
8719
8720INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
8721{
8722 // TODO Implement me!
8723 return RETURN_ERR;
8724}
8725
8726INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
8727{
8728 // TODO Implement me!
8729 return RETURN_ERR;
8730}
8731
8732INT wifi_steering_eventUnregister(void)
8733{
8734 // TODO Implement me!
8735 return RETURN_ERR;
8736}
8737
8738INT wifi_delApAclDevices(INT apIndex)
8739{
8740#if 0
8741 char cmd[MAX_BUF_SIZE] = {0};
8742 char buf[MAX_BUF_SIZE] = {0};
8743
8744 /* Not reset proof solution */
8745 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
8746 if(_syscmd(cmd,buf,sizeof(buf)))
8747 return RETURN_ERR;
8748#endif
developere6aafda2022-09-13 14:59:28 +08008749 char cmd[MAX_CMD_SIZE]={0};
8750 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08008751
developere6aafda2022-09-13 14:59:28 +08008752 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8753 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
8754 if(_syscmd(cmd, buf, sizeof(buf)))
8755 return RETURN_ERR;
8756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008757
8758 return RETURN_OK;
8759}
8760
8761#ifdef HAL_NETLINK_IMPL
8762static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
8763 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8764 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8765 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8766 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
8767 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
8768 char mac_addr[20],dev[20];
8769
8770 nla_parse(tb,
8771 NL80211_ATTR_MAX,
8772 genlmsg_attrdata(gnlh, 0),
8773 genlmsg_attrlen(gnlh, 0),
8774 NULL);
8775
8776 if(!tb[NL80211_ATTR_STA_INFO]) {
8777 fprintf(stderr, "sta stats missing!\n");
8778 return NL_SKIP;
8779 }
8780
8781 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
8782 fprintf(stderr, "failed to parse nested attributes!\n");
8783 return NL_SKIP;
8784 }
8785 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
8786
8787 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8788
8789 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
8790 fprintf(stderr, "failed to parse nested rate attributes!");
8791 return NL_SKIP;
8792 }
8793
8794 if(sinfo[NL80211_STA_INFO_TID_STATS])
8795 {
8796 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
8797 printf("failed to parse nested stats attributes!");
8798 return NL_SKIP;
8799 }
8800 }
8801
8802 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
8803 {
8804 printf("Type is VHT\n");
8805 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
8806 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
8807
8808 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
8809 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
8810 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
8811 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8812 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
8813 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8814 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
8815 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8816 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
8817 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
8818 }
8819 else
8820 {
8821 printf(" OFDM or CCK \n");
8822 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
8823 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
8824 }
8825
8826 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
8827 if(rinfo[NL80211_RATE_INFO_MCS])
8828 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
8829 }
8830 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
8831 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
8832 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
8833 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
8834
8835 if(stats_info[NL80211_TID_STATS_RX_MSDU])
8836 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
8837
8838 if (sinfo[NL80211_STA_INFO_SIGNAL])
8839 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
8840 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
8841 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
8842 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
8843 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
8844 //rssi_array need to be filled
8845 return NL_SKIP;
8846}
8847#endif
8848
8849INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
8850{
8851#ifdef HAL_NETLINK_IMPL
8852 Netlink nl;
8853 char if_name[10];
8854
8855 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
8856
8857 if (*output_array_size <= 0)
8858 return RETURN_OK;
8859
8860 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8861 nl.id = initSock80211(&nl);
8862
8863 if (nl.id < 0) {
8864 fprintf(stderr, "Error initializing netlink \n");
8865 return 0;
8866 }
8867
8868 struct nl_msg* msg = nlmsg_alloc();
8869
8870 if (!msg) {
8871 fprintf(stderr, "Failed to allocate netlink message.\n");
8872 nlfree(&nl);
8873 return 0;
8874 }
8875
8876 genlmsg_put(msg,
8877 NL_AUTO_PORT,
8878 NL_AUTO_SEQ,
8879 nl.id,
8880 0,
8881 0,
8882 NL80211_CMD_GET_STATION,
8883 0);
8884
8885 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
8886 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8887 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
8888 nl_send_auto(nl.socket, msg);
8889 nl_recvmsgs(nl.socket, nl.cb);
8890 nlmsg_free(msg);
8891 nlfree(&nl);
8892 return RETURN_OK;
8893#else
8894 //TODO Implement me
8895 return RETURN_OK;
8896#endif
8897}
8898
8899#ifdef HAL_NETLINK_IMPL
8900static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
8901 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8902 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8903 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8904 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
8905 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
8906 char mac_addr[20],dev[20];
8907
8908 nla_parse(tb,
8909 NL80211_ATTR_MAX,
8910 genlmsg_attrdata(gnlh, 0),
8911 genlmsg_attrlen(gnlh, 0),
8912 NULL);
8913
8914 if(!tb[NL80211_ATTR_STA_INFO]) {
8915 fprintf(stderr, "sta stats missing!\n");
8916 return NL_SKIP;
8917 }
8918
8919 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
8920 fprintf(stderr, "failed to parse nested attributes!\n");
8921 return NL_SKIP;
8922 }
8923
8924 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
8925
8926 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8927
8928 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
8929 fprintf(stderr, "failed to parse nested rate attributes!");
8930 return NL_SKIP;
8931 }
8932
8933 if(sinfo[NL80211_STA_INFO_TID_STATS])
8934 {
8935 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
8936 printf("failed to parse nested stats attributes!");
8937 return NL_SKIP;
8938 }
8939 }
8940 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
8941 {
8942 printf("Type is VHT\n");
8943 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
8944 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
8945
8946 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
8947 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
8948 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
8949 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8950 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
8951 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8952 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
8953 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8954 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
8955 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
8956 }
8957 else
8958 {
8959 printf(" OFDM or CCK \n");
8960 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
8961 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
8962 }
8963
8964 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
8965 if(rinfo[NL80211_RATE_INFO_MCS])
8966 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
8967 }
8968
8969 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
8970 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
8971 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
8972 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
8973
8974 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
8975 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
8976 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
8977
8978 if(stats_info[NL80211_TID_STATS_TX_MSDU])
8979 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
8980
8981 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
8982 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
8983
8984 if(sinfo[NL80211_STA_INFO_TX_FAILED])
8985 ((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]);
8986
8987 return NL_SKIP;
8988}
8989#endif
8990
8991INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
8992{
8993#ifdef HAL_NETLINK_IMPL
8994 Netlink nl;
8995 char if_name[10];
8996
8997 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
8998
8999 if (*output_array_size <= 0)
9000 return RETURN_OK;
9001
9002 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9003
9004 nl.id = initSock80211(&nl);
9005
9006 if(nl.id < 0) {
9007 fprintf(stderr, "Error initializing netlink \n");
9008 return 0;
9009 }
9010
9011 struct nl_msg* msg = nlmsg_alloc();
9012
9013 if(!msg) {
9014 fprintf(stderr, "Failed to allocate netlink message.\n");
9015 nlfree(&nl);
9016 return 0;
9017 }
9018
9019 genlmsg_put(msg,
9020 NL_AUTO_PORT,
9021 NL_AUTO_SEQ,
9022 nl.id,
9023 0,
9024 0,
9025 NL80211_CMD_GET_STATION,
9026 0);
9027
9028 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9029 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9030 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9031 nl_send_auto(nl.socket, msg);
9032 nl_recvmsgs(nl.socket, nl.cb);
9033 nlmsg_free(msg);
9034 nlfree(&nl);
9035 return RETURN_OK;
9036#else
9037 //TODO Implement me
9038 return RETURN_OK;
9039#endif
9040}
9041
9042INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9043{
9044 // TODO Implement me!
9045 char buf[MAX_BUF_SIZE] = {0};
9046 char config_file[MAX_BUF_SIZE] = {0};
9047
9048 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9049 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9050 *activate = (strncmp("1",buf,1) == 0);
9051
9052 return RETURN_OK;
9053}
9054
9055INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9056{
9057 char config_file[MAX_BUF_SIZE] = {0};
9058 struct params list;
9059
9060 list.name = "rrm_neighbor_report";
9061 list.value = activate?"1":"0";
9062 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9063 wifi_hostapdWrite(config_file, &list, 1);
9064
9065 return RETURN_OK;
9066}
9067
9068INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9069{
9070 char buf[32] = {0};
9071 char config_file[MAX_BUF_SIZE] = {0};
9072
9073 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9074 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9075 *activate = (strncmp("1",buf,1) == 0);
9076
9077 return RETURN_OK;
9078}
9079#undef HAL_NETLINK_IMPL
9080#ifdef HAL_NETLINK_IMPL
9081static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9082 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9083 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9084 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9085 char dev[20];
9086 int freq =0 ;
9087 static int i=0;
9088
9089 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9090
9091 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9092 };
9093
9094 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9095
9096 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9097
9098 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9099 fprintf(stderr, "survey data missing!\n");
9100 return NL_SKIP;
9101 }
9102
9103 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9104 {
9105 fprintf(stderr, "failed to parse nested attributes!\n");
9106 return NL_SKIP;
9107 }
9108
9109
9110 if(out[0].array_size == 1 )
9111 {
9112 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9113 {
9114 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9115 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9116 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9117
9118 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9119 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9120 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9121 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9122 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9123 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9124 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9125 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9126 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9127 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9128 if (sinfo[NL80211_SURVEY_INFO_TIME])
9129 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9130 return NL_STOP;
9131 }
9132 }
9133 else
9134 {
9135 if ( i <= out[0].array_size )
9136 {
9137 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9138 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9139 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9140
9141 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9142 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9143 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9144 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9145 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9146 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9147 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9148 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9149 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9150 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9151 if (sinfo[NL80211_SURVEY_INFO_TIME])
9152 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9153 }
9154 }
9155
9156 i++;
9157 return NL_SKIP;
9158}
9159#endif
9160
9161static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9162{
9163 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9164 FILE *fp;
9165
9166 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9167 {
9168 printf("Creating Frequency-Channel Map\n");
9169 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9170 }
9171 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9172 if((fp = popen(command, "r")))
9173 {
9174 fgets(output, sizeof(output), fp);
9175 *freqMHz = atoi(output);
9176 fclose(fp);
9177 }
9178
9179 return 0;
9180}
9181
9182static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9183{
9184 int freqMHz = -1;
9185 char cmd[MAX_CMD_SIZE] = {'\0'};
9186
9187 ieee80211_channel_to_frequency(channel, &freqMHz);
9188 if (freqMHz == -1) {
9189 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9190 return -1;
9191 }
9192
9193 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9194 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9195 radioIndex, freqMHz);
9196 return -1;
9197 }
9198
9199 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9200 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9201 return -1;
9202 }
9203
9204 return 0;
9205}
9206
9207static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9208{
9209 const char *ptr = buf;
9210 char *key = NULL;
9211 char *val = NULL;
9212 char line[256] = { '\0' };
9213
9214 while (ptr = get_line_from_str_buf(ptr, line)) {
9215 if (strstr(line, "Frequency")) continue;
9216
9217 key = strtok(line, ":");
9218 val = strtok(NULL, " ");
9219 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9220
9221 if (!strcmp(key, "noise")) {
9222 sscanf(val, "%d", &stats->ch_noise);
9223 if (stats->ch_noise == 0) {
9224 // Workaround for missing noise information.
9225 // Assume -95 for 2.4G and -103 for 5G
9226 if (radioIndex == 0) stats->ch_noise = -95;
9227 if (radioIndex == 1) stats->ch_noise = -103;
9228 }
9229 }
9230 else if (!strcmp(key, "channel active time")) {
9231 sscanf(val, "%llu", &stats->ch_utilization_total);
9232 }
9233 else if (!strcmp(key, "channel busy time")) {
9234 sscanf(val, "%llu", &stats->ch_utilization_busy);
9235 }
9236 else if (!strcmp(key, "channel receive time")) {
9237 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9238 }
9239 else if (!strcmp(key, "channel transmit time")) {
9240 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9241 }
9242 };
9243
9244 return 0;
9245}
9246
9247INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9248{
9249 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9250#ifdef HAL_NETLINK_IMPL
9251 Netlink nl;
9252 wifi_channelStats_t_loc local[array_size];
9253 char if_name[10];
9254
9255 local[0].array_size = array_size;
9256
9257 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9258
9259 nl.id = initSock80211(&nl);
9260
9261 if (nl.id < 0) {
9262 fprintf(stderr, "Error initializing netlink \n");
9263 return -1;
9264 }
9265
9266 struct nl_msg* msg = nlmsg_alloc();
9267
9268 if (!msg) {
9269 fprintf(stderr, "Failed to allocate netlink message.\n");
9270 nlfree(&nl);
9271 return -2;
9272 }
9273
9274 genlmsg_put(msg,
9275 NL_AUTO_PORT,
9276 NL_AUTO_SEQ,
9277 nl.id,
9278 0,
9279 NLM_F_DUMP,
9280 NL80211_CMD_GET_SURVEY,
9281 0);
9282
9283 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9284 nl_send_auto(nl.socket, msg);
9285 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9286 nl_recvmsgs(nl.socket, nl.cb);
9287 nlmsg_free(msg);
9288 nlfree(&nl);
9289 //Copying the Values
9290 for(int i=0;i<array_size;i++)
9291 {
9292 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9293 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9294 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9295 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9296 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9297 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9298 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9299 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9300 }
9301#else
9302 ULONG channel = 0;
9303 int i;
9304 int number_of_channels = array_size;
9305 char buf[512];
9306 INT ret;
9307 wifi_channelStats_t tmp_stats;
9308
9309 if (number_of_channels == 0) {
9310 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9311 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9312 return RETURN_ERR;
9313 }
9314 number_of_channels = 1;
9315 input_output_channelStats_array[0].ch_number = channel;
9316 }
9317
9318 for (i = 0; i < number_of_channels; i++) {
9319
9320 input_output_channelStats_array[i].ch_noise = 0;
9321 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9322 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9323 input_output_channelStats_array[i].ch_utilization_busy = 0;
9324 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9325 input_output_channelStats_array[i].ch_utilization_total = 0;
9326
9327 memset(buf, 0, sizeof(buf));
9328 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9329 return RETURN_ERR;
9330 }
9331 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9332 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9333 return RETURN_ERR;
9334 }
9335
9336 // XXX: fake missing 'self' counter which is not available in iw survey output
9337 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9338 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9339
9340 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9341 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9342 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9343 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9344 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9345
9346 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",
9347 __func__,
9348 input_output_channelStats_array[i].ch_number,
9349 input_output_channelStats_array[i].ch_noise,
9350 input_output_channelStats_array[i].ch_utilization_total,
9351 input_output_channelStats_array[i].ch_utilization_busy,
9352 input_output_channelStats_array[i].ch_utilization_busy_rx,
9353 input_output_channelStats_array[i].ch_utilization_busy_tx,
9354 input_output_channelStats_array[i].ch_utilization_busy_self,
9355 input_output_channelStats_array[i].ch_utilization_busy_ext);
9356 }
9357#endif
9358 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9359 return RETURN_OK;
9360}
9361#define HAL_NETLINK_IMPL
9362
9363/* Hostapd events */
9364
9365#ifndef container_of
9366#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9367#define container_of(ptr, type, member) \
9368 ((type *)((char *)ptr - offset_of(type, member)))
9369#endif /* container_of */
9370
9371struct ctrl {
9372 char sockpath[128];
9373 char sockdir[128];
9374 char bss[IFNAMSIZ];
9375 char reply[4096];
9376 int ssid_index;
9377 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9378 void (*overrun)(struct ctrl *ctrl);
9379 struct wpa_ctrl *wpa;
9380 unsigned int ovfl;
9381 size_t reply_len;
9382 int initialized;
9383 ev_timer retry;
9384 ev_timer watchdog;
9385 ev_stat stat;
9386 ev_io io;
9387};
9388static wifi_newApAssociatedDevice_callback clients_connect_cb;
9389static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9390static struct ctrl wpa_ctrl[MAX_APS];
9391static int initialized;
9392
9393static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9394{
9395 char cbuf[256] = {};
9396 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9397 struct cmsghdr *cmsg;
9398 unsigned int ovfl = ctrl->ovfl;
9399 unsigned int drop;
9400
9401 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9402 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9403 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9404 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9405
9406 drop = ovfl - ctrl->ovfl;
9407 ctrl->ovfl = ovfl;
9408
9409 return drop;
9410}
9411
9412static void ctrl_close(struct ctrl *ctrl)
9413{
9414 if (ctrl->io.cb)
9415 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9416 if (ctrl->retry.cb)
9417 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9418 if (!ctrl->wpa)
9419 return;
9420
9421 wpa_ctrl_detach(ctrl->wpa);
9422 wpa_ctrl_close(ctrl->wpa);
9423 ctrl->wpa = NULL;
9424 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9425}
9426
9427static void ctrl_process(struct ctrl *ctrl)
9428{
9429 const char *str;
9430 int drops;
9431 int level;
9432 int err;
9433
9434 /* Example events:
9435 *
9436 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9437 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9438 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9439 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9440 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9441 */
9442 if (!(str = index(ctrl->reply, '>')))
9443 return;
9444 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9445 return;
9446
9447 str++;
9448
9449 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9450 if (!(str = index(ctrl->reply, ' ')))
9451 return;
9452 wifi_associated_dev_t sta;
9453 memset(&sta, 0, sizeof(sta));
9454
9455 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9456 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9457 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9458
9459 sta.cli_Active=true;
9460
9461 (clients_connect_cb)(ctrl->ssid_index, &sta);
9462 goto handled;
9463 }
9464
9465 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9466 if (!(str = index(ctrl->reply, ' ')))
9467 return;
9468
9469 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9470 goto handled;
9471 }
9472
9473 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9474 printf("CTRL_WPA: handle TERMINATING event\n");
9475 goto retry;
9476 }
9477
9478 if (strncmp("AP-DISABLED", str, 11) == 0) {
9479 printf("CTRL_WPA: handle AP-DISABLED\n");
9480 goto retry;
9481 }
9482
9483 printf("Event not supported!!\n");
9484
9485handled:
9486
9487 if ((drops = ctrl_get_drops(ctrl))) {
9488 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
9489 if (ctrl->overrun)
9490 ctrl->overrun(ctrl);
9491 }
9492
9493 return;
9494
9495retry:
9496 printf("WPA_CTRL: closing\n");
9497 ctrl_close(ctrl);
9498 printf("WPA_CTRL: retrying from ctrl prcoess\n");
9499 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
9500}
9501
9502static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
9503{
9504 struct ctrl *ctrl = container_of(io, struct ctrl, io);
9505 int err;
9506
9507 memset(ctrl->reply, 0, sizeof(ctrl->reply));
9508 ctrl->reply_len = sizeof(ctrl->reply) - 1;
9509 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
9510 ctrl->reply[ctrl->reply_len] = 0;
9511 if (err < 0) {
9512 if (errno == EAGAIN || errno == EWOULDBLOCK)
9513 return;
9514 ctrl_close(ctrl);
9515 ev_timer_again(EV_A_ &ctrl->retry);
9516 return;
9517 }
9518
9519 ctrl_process(ctrl);
9520}
9521
9522static int ctrl_open(struct ctrl *ctrl)
9523{
9524 int fd;
9525
9526 if (ctrl->wpa)
9527 return 0;
9528
9529 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
9530 if (!ctrl->wpa)
9531 goto err;
9532
9533 if (wpa_ctrl_attach(ctrl->wpa) < 0)
9534 goto err_close;
9535
9536 fd = wpa_ctrl_get_fd(ctrl->wpa);
9537 if (fd < 0)
9538 goto err_detach;
9539
9540 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
9541 goto err_detach;
9542
9543 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
9544 ev_io_start(EV_DEFAULT_ &ctrl->io);
9545
9546 return 0;
9547
9548err_detach:
9549 wpa_ctrl_detach(ctrl->wpa);
9550err_close:
9551 wpa_ctrl_close(ctrl->wpa);
9552err:
9553 ctrl->wpa = NULL;
9554 return -1;
9555}
9556
9557static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
9558{
9559 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
9560
9561 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
9562 ctrl_open(ctrl);
9563}
9564
9565static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
9566{
9567 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
9568
9569 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
9570 if (ctrl_open(ctrl) == 0) {
9571 printf("WPA_CTRL: retry successful\n");
9572 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9573 }
9574}
9575
9576int ctrl_enable(struct ctrl *ctrl)
9577{
9578 if (ctrl->wpa)
9579 return 0;
9580
9581 if (!ctrl->stat.cb) {
9582 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
9583 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
9584 }
9585
9586 if (!ctrl->retry.cb) {
9587 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
9588 }
9589
9590 return ctrl_open(ctrl);
9591}
9592
9593static void
9594ctrl_msg_cb(char *buf, size_t len)
9595{
9596 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
9597
9598 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
9599 ctrl_process(ctrl);
9600}
9601
9602static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
9603{
9604 int err;
9605
9606 if (!ctrl->wpa)
9607 return -1;
9608 if (*reply_len < 2)
9609 return -1;
9610
9611 (*reply_len)--;
9612 ctrl->reply_len = sizeof(ctrl->reply);
9613 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
9614 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
9615 if (err < 0)
9616 return err;
9617
9618 if (ctrl->reply_len > *reply_len)
9619 ctrl->reply_len = *reply_len;
9620
9621 *reply_len = ctrl->reply_len;
9622 memcpy(reply, ctrl->reply, *reply_len);
9623 reply[*reply_len - 1] = 0;
9624 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
9625 return 0;
9626}
9627
9628static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
9629{
9630 const char *pong = "PONG";
9631 const char *ping = "PING";
9632 char reply[1024];
9633 size_t len = sizeof(reply);
9634 int err;
9635 ULONG s, snum;
9636 INT ret;
9637 BOOL status;
9638
9639 printf("WPA_CTRL: watchdog cb\n");
9640
9641 ret = wifi_getSSIDNumberOfEntries(&snum);
9642 if (ret != RETURN_OK) {
9643 printf("%s: failed to get SSID count", __func__);
9644 return;
9645 }
9646
9647 if (snum > MAX_APS) {
9648 printf("more ssid than supported! %lu\n", snum);
9649 return;
9650 }
9651
9652 for (s = 0; s < snum; s++) {
9653 if (wifi_getApEnable(s, &status) != RETURN_OK) {
9654 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
9655 continue;
9656 }
9657 if (status == false) continue;
9658
9659 memset(reply, 0, sizeof(reply));
9660 len = sizeof(reply);
9661 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
9662 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
9663 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
9664 continue;
9665
9666 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
9667 ctrl_close(&wpa_ctrl[s]);
9668 printf("WPA_CTRL: ev_timer_again %d\n", s);
9669 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
9670 }
9671}
9672
9673static int init_wpa()
9674{
9675 int ret = 0, i = 0;
9676 ULONG s, snum;
9677
9678 ret = wifi_getSSIDNumberOfEntries(&snum);
9679 if (ret != RETURN_OK) {
9680 printf("%s: failed to get SSID count", __func__);
9681 return RETURN_ERR;
9682 }
9683
9684 if (snum > MAX_APS) {
9685 printf("more ssid than supported! %lu\n", snum);
9686 return RETURN_ERR;
9687 }
9688
9689 for (s = 0; s < snum; s++) {
9690 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
9691 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
9692 wpa_ctrl[s].ssid_index = s;
9693 ctrl_enable(&wpa_ctrl[s]);
9694 }
9695
9696 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
9697 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
9698
9699 initialized = 1;
9700 printf("WPA_CTRL: initialized\n");
9701
9702 return RETURN_OK;
9703}
9704
9705void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
9706{
9707 clients_connect_cb = callback_proc;
9708 if (!initialized)
9709 init_wpa();
9710}
9711
9712void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
9713{
9714 clients_disconnect_cb = callback_proc;
9715 if (!initialized)
9716 init_wpa();
9717}
9718
9719INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
9720{
9721 // TODO Implement me!
9722 return RETURN_ERR;
9723}
9724
9725INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
9726{
9727 // TODO Implement me!
9728 return RETURN_ERR;
9729}
9730
9731INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
9732{
9733 int i;
9734 char cmd[256];
9735 char channel_numbers_buf[256];
9736 char dfs_state_buf[256];
9737 char line[256];
9738 const char *ptr;
9739
9740 memset(cmd, 0, sizeof(cmd));
9741 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
9742 memset(line, 0, sizeof(line));
9743 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
9744 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
9745
9746 if (radioIndex == 0) { // 2.4G - all allowed
9747 if (outputMapSize < 11) {
9748 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
9749 return RETURN_ERR;
9750 }
9751
9752 for (i = 0; i < 11; i++) {
9753 outputMap[i].ch_number = i + 1;
9754 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
9755 }
9756
9757 return RETURN_OK;
9758 }
9759
9760 if (radioIndex == 1) { // 5G
9761// Example output of iw list:
9762//
9763// Frequencies:
9764// * 5180 MHz [36] (17.0 dBm)
9765// * 5200 MHz [40] (17.0 dBm)
9766// * 5220 MHz [44] (17.0 dBm)
9767// * 5240 MHz [48] (17.0 dBm)
9768// * 5260 MHz [52] (23.0 dBm) (radar detection)
9769// DFS state: usable (for 78930 sec)
9770// DFS CAC time: 60000 ms
9771// * 5280 MHz [56] (23.0 dBm) (radar detection)
9772// DFS state: usable (for 78930 sec)
9773// DFS CAC time: 60000 ms
9774// * 5300 MHz [60] (23.0 dBm) (radar detection)
9775// DFS state: usable (for 78930 sec)
9776// DFS CAC time: 60000 ms
9777// * 5320 MHz [64] (23.0 dBm) (radar detection)
9778// DFS state: usable (for 78930 sec)
9779// DFS CAC time: 60000 ms
9780// * 5500 MHz [100] (disabled)
9781// * 5520 MHz [104] (disabled)
9782// * 5540 MHz [108] (disabled)
9783// * 5560 MHz [112] (disabled)
9784//
9785// Below command should fetch channel numbers of each enabled channel in 5GHz band:
9786 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
9787 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
9788 return RETURN_ERR;
9789 }
9790
9791 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
9792 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9793 return RETURN_ERR;
9794 }
9795
9796 ptr = channel_numbers_buf;
9797 i = 0;
9798 while (ptr = get_line_from_str_buf(ptr, line)) {
9799 if (i >= outputMapSize) {
9800 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
9801 return RETURN_ERR;
9802 }
9803 sscanf(line, "%d", &outputMap[i].ch_number);
9804
9805 memset(cmd, 0, sizeof(cmd));
9806 // Below command should fetch string for DFS state (usable, available or unavailable)
9807 // Example line: "DFS state: usable (for 78930 sec)"
9808 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) {
9809 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
9810 return RETURN_ERR;
9811 }
9812
9813 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
9814 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
9815 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9816 return RETURN_ERR;
9817 }
9818
9819 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
9820
9821 if (!strcmp(dfs_state_buf, "usable")) {
9822 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
9823 } else if (!strcmp(dfs_state_buf, "available")) {
9824 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
9825 } else if (!strcmp(dfs_state_buf, "unavailable")) {
9826 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
9827 } else {
9828 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
9829 }
9830 i++;
9831 }
9832
9833 return RETURN_OK;
9834 }
9835
9836 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
9837 return RETURN_ERR;
9838}
9839
9840INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
9841{
9842 // TODO Implement me!
9843 return RETURN_ERR;
9844}
9845
9846INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
9847{
9848 return RETURN_OK;
9849}
9850
9851INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
9852{
9853 // TODO Implement me!
9854 return RETURN_ERR;
9855}
9856
9857INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
9858{
9859 // TODO API refrence Implementaion is present on RPI hal
9860 return RETURN_ERR;
9861}
9862
9863INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
9864{
developera5005b62022-09-13 15:43:35 +08009865 char cmd[128]={'\0'};
9866 char buf[128]={'\0'};
9867 char *support;
9868 int maximum_tx = 0, current_tx = 0;
9869
9870 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9871 if(txpwr_pcntg == NULL)
9872 return RETURN_ERR;
9873
9874 // Get the maximum tx power of the device
9875 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
9876 _syscmd(cmd, buf, sizeof(buf));
9877 maximum_tx = strtol(buf, NULL, 10);
9878
9879 // Get the current tx power
9880 memset(cmd, 0, sizeof(cmd));
9881 memset(buf, 0, sizeof(buf));
9882 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
9883 _syscmd(cmd, buf, sizeof(buf));
9884 current_tx = strtol(buf, NULL, 10);
9885
9886 // Get the power supported list and find the current power percentage in supported list
9887 memset(buf, 0, sizeof(buf));
9888 wifi_getRadioTransmitPowerSupported(apIndex, buf);
9889 support = strtok(buf, ",");
9890 while(true)
9891 {
9892 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
9893 *txpwr_pcntg = 0;
9894 wifi_dbg_printf("current power is not in supported list\n");
9895 return RETURN_ERR;
9896 }
9897 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
9898 if (tmp == current_tx) {
9899 *txpwr_pcntg = strtol(support, NULL, 10);
9900 break;
9901 }
9902 support = strtok(NULL, ",");
9903 }
9904 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009905 return RETURN_OK;
9906}
9907
9908INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
9909{
9910 //Zero-wait DFS not supported
9911 return RETURN_ERR;
9912}
9913
9914INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
9915{
9916 //Zero-wait DFS not supported
9917 return RETURN_ERR;
9918}
9919
9920INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
9921{
9922 *supported = false;
9923 return RETURN_OK;
9924}
9925
developer454b9462022-09-13 15:29:16 +08009926INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
9927{
9928 char cmd[128] = {0};
9929 char buf[64] = {0};
9930 char band_str[8] = {0};
9931 char GI[8] = {0};
9932 int tmp = 0;
9933 BOOL ax_mode = FALSE;
9934 BOOL short_GI = FALSE;
9935 FILE *f = NULL;
9936 wifi_band band;
9937
9938 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9939
9940 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
9941 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
9942 return RETURN_ERR;
9943 }
9944 if (strstr(buf, "ax") != NULL)
9945 ax_mode = TRUE;
9946
9947 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
9948 short_GI = TRUE;
9949 strcpy(GI, "0.4");
9950 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
9951 strcpy(GI, "1.6");
9952 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
9953 strcpy(GI, "3.2");
9954 else // default
9955 strcpy(GI, "0.8");
9956
9957 band = wifi_index_to_band(radio_index);
9958 if (band == band_2_4)
9959 strcpy(band_str, "2.4");
9960 else if (band == band_5)
9961 strcpy(band_str, "5");
9962 else if (band == band_6)
9963 strcpy(band_str, "6");
9964 else {
9965 wifi_dbg_printf("%s: invalid band\n");
9966 return RETURN_ERR;
9967 }
9968
9969 if (ax_mode == TRUE)
9970 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
9971 else
9972 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
9973 _syscmd(cmd, buf, sizeof(buf));
9974
9975 // Record GI for get GI function
9976 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
9977 f = fopen(buf, "w");
9978 if (f != NULL) {
9979 fprintf(f, "%s", GI);
9980 }
9981 fclose(f);
9982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9983 return RETURN_OK;
9984}
9985
9986INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
9987{
9988 char buf[32] = {0};
9989 char cmd[64] = {0};
9990
9991 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9992
9993 if (guard_interval == NULL)
9994 return RETURN_ERR;
9995
9996 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
9997 _syscmd(cmd, buf, sizeof(buf));
9998
9999 if (strncmp(buf, "0.4", 3) == 0)
10000 *guard_interval = wifi_guard_interval_400;
10001 else if (strncmp(buf, "0.8", 3) == 0)
10002 *guard_interval = wifi_guard_interval_800;
10003 else if (strncmp(buf, "1.6", 3) == 0)
10004 *guard_interval = wifi_guard_interval_1600;
10005 else if (strncmp(buf, "3.2", 3) == 0)
10006 *guard_interval = wifi_guard_interval_3200;
10007 else
10008 *guard_interval = wifi_guard_interval_auto;
10009
10010 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10011 return RETURN_OK;
10012}
10013
developer3cc61d12022-09-13 16:36:05 +080010014INT wifi_setBSSColor(INT radio_index, UCHAR color)
10015{
10016 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10017 struct params params = {0};
10018 char config_file[128] = {0};
10019 char bss_color[4] ={0};
10020
10021 params.name = "he_bss_color";
10022 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10023 params.value = bss_color;
10024 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10025 wifi_hostapdWrite(config_file, &params, 1);
10026 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10027
10028 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10029 return RETURN_OK;
10030}
10031
10032INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10033{
10034 char config_file[128] = {0};
10035 char buf[64] = {0};
10036 char temp_output[128] = {'\0'};
10037
10038 wifi_dbg_printf("\nFunc=%s\n", __func__);
10039 if (NULL == color)
10040 return RETURN_ERR;
10041
10042 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10043 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10044
10045 if(strlen(buf) > 0) {
10046 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10047 } else {
10048 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10049 }
10050
10051 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10052 wifi_dbg_printf("\noutput_string=%s\n", color);
10053
10054 return RETURN_OK;
10055}
10056
developer06a01d92022-09-07 16:32:39 +080010057/* multi-psk support */
10058INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10059{
10060 char cmd[256];
10061
10062 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10063 AP_PREFIX,
10064 apIndex,
10065 mac[0],
10066 mac[1],
10067 mac[2],
10068 mac[3],
10069 mac[4],
10070 mac[5]
10071 );
10072 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10073 _syscmd(cmd, key->wifi_keyId, 64);
10074
10075
10076 return RETURN_OK;
10077}
10078
10079INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10080{
10081 FILE *fd = NULL;
10082 char fname[100];
10083 char cmd[128] = {0};
10084 char out[64] = {0};
10085 wifi_key_multi_psk_t * key = NULL;
10086 if(keysNumber < 0)
10087 return RETURN_ERR;
10088
10089 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10090 fd = fopen(fname, "w");
10091 if (!fd) {
10092 return RETURN_ERR;
10093 }
10094 key= (wifi_key_multi_psk_t *) keys;
10095 for(int i=0; i<keysNumber; ++i, key++) {
10096 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10097 }
10098 fclose(fd);
10099
10100 //reload file
10101 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10102 _syscmd(cmd, out, 64);
10103 return RETURN_OK;
10104}
10105
10106INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10107{
10108 FILE *fd = NULL;
10109 char fname[100];
10110 char * line = NULL;
10111 char * pos = NULL;
10112 size_t len = 0;
10113 ssize_t read = 0;
10114 INT ret = RETURN_OK;
10115 wifi_key_multi_psk_t *keys_it = NULL;
10116
10117 if (keysNumber < 1) {
10118 return RETURN_ERR;
10119 }
10120
10121 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10122 fd = fopen(fname, "r");
10123 if (!fd) {
10124 return RETURN_ERR;
10125 }
10126
10127 if (keys == NULL) {
10128 ret = RETURN_ERR;
10129 goto close;
10130 }
10131
10132 keys_it = keys;
10133 while ((read = getline(&line, &len, fd)) != -1) {
10134 //Strip trailing new line if present
10135 if (read > 0 && line[read-1] == '\n') {
10136 line[read-1] = '\0';
10137 }
10138
10139 if(strcmp(line,"keyid=")) {
10140 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10141 if (!(pos = index(line, ' '))) {
10142 ret = RETURN_ERR;
10143 goto close;
10144 }
10145 pos++;
10146 //Here should be 00:00:00:00:00:00
10147 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10148 printf("Not supported MAC: %s\n", pos);
10149 }
10150 if (!(pos = index(pos, ' '))) {
10151 ret = RETURN_ERR;
10152 goto close;
10153 }
10154 pos++;
10155
10156 //The rest is PSK
10157 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10158 keys_it++;
10159
10160 if(--keysNumber <= 0)
10161 break;
10162 }
10163 }
10164
10165close:
10166 free(line);
10167 fclose(fd);
10168 return ret;
10169}
10170/* end of multi-psk support */
10171
10172INT wifi_setNeighborReports(UINT apIndex,
10173 UINT numNeighborReports,
10174 wifi_NeighborReport_t *neighborReports)
10175{
10176 char cmd[256] = { 0 };
10177 char hex_bssid[13] = { 0 };
10178 char bssid[18] = { 0 };
10179 char nr[256] = { 0 };
10180 char ssid[256];
10181 char hex_ssid[256];
10182 INT ret;
10183
10184 /*rmeove all neighbors*/
10185 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10186 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);
10187 system(cmd);
10188
10189 for(unsigned int i = 0; i < numNeighborReports; i++)
10190 {
10191 memset(ssid, 0, sizeof(ssid));
10192 ret = wifi_getSSIDName(apIndex, ssid);
10193 if (ret != RETURN_OK)
10194 return RETURN_ERR;
10195
10196 memset(hex_ssid, 0, sizeof(hex_ssid));
10197 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10198 sprintf(hex_ssid + k,"%02x", ssid[j]);
10199
10200 snprintf(hex_bssid, sizeof(hex_bssid),
10201 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10202 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10203 snprintf(bssid, sizeof(bssid),
10204 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10205 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10206
10207 snprintf(nr, sizeof(nr),
10208 "%s" // bssid
10209 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10210 "%02hhx" // operclass
10211 "%02hhx" // channel
10212 "%02hhx", // phy_mode
10213 hex_bssid,
10214 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10215 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10216 neighborReports[i].opClass,
10217 neighborReports[i].channel,
10218 neighborReports[i].phyTable);
10219
10220 snprintf(cmd, sizeof(cmd),
10221 "hostapd_cli set_neighbor "
10222 "%s " // bssid
10223 "ssid=%s " // ssid
10224 "nr=%s " // nr
10225 "-i %s%d",
10226 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10227
10228 if (WEXITSTATUS(system(cmd)) != 0)
10229 {
10230 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10231 }
10232 }
10233
10234 return RETURN_OK;
10235}
10236
10237INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10238{
10239 return RETURN_OK;
10240}
10241
10242#ifdef _WIFI_HAL_TEST_
10243int main(int argc,char **argv)
10244{
10245 int index;
10246 INT ret=0;
10247 char buf[1024]="";
10248
10249 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10250 if(argc<3)
10251 {
10252 if(argc==2)
10253 {
10254 if(!strcmp(argv[1], "init"))
10255 return wifi_init();
10256 if(!strcmp(argv[1], "reset"))
10257 return wifi_reset();
10258 if(!strcmp(argv[1], "wifi_getHalVersion"))
10259 {
10260 char buffer[64];
10261 if(wifi_getHalVersion(buffer)==RETURN_OK)
10262 printf("Version: %s\n", buffer);
10263 else
10264 printf("Error in wifi_getHalVersion\n");
10265 return RETURN_OK;
10266 }
10267 }
10268 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10269 exit(-1);
10270 }
10271
10272 index = atoi(argv[2]);
10273 if(strstr(argv[1], "wifi_getApName")!=NULL)
10274 {
10275 wifi_getApName(index,buf);
10276 printf("Ap name is %s \n",buf);
10277 return 0;
10278 }
10279 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10280 {
10281 BOOL b = FALSE;
10282 BOOL *output_bool = &b;
10283 wifi_getRadioAutoChannelEnable(index,output_bool);
10284 printf("Channel enabled = %d \n",b);
10285 return 0;
10286 }
10287 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10288 {
10289 wifi_getApWpaEncryptionMode(index,buf);
10290 printf("encryption enabled = %s\n",buf);
10291 return 0;
10292 }
10293 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10294 {
10295 BOOL b = FALSE;
10296 BOOL *output_bool = &b;
10297 wifi_getApSsidAdvertisementEnable(index,output_bool);
10298 printf("advertisment enabled = %d\n",b);
10299 return 0;
10300 }
10301 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10302 {
10303 if(argc <= 3 )
10304 {
10305 printf("Insufficient arguments \n");
10306 exit(-1);
10307 }
10308
10309 char sta[20] = {'\0'};
10310 ULLONG handle= 0;
10311 strcpy(sta,argv[3]);
10312 mac_address_t st;
10313 mac_addr_aton(st,sta);
10314
10315 wifi_associated_dev_tid_stats_t tid_stats;
10316 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10317 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10318 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);
10319 }
10320
10321 if(strstr(argv[1], "getApEnable")!=NULL) {
10322 BOOL enable;
10323 ret=wifi_getApEnable(index, &enable);
10324 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10325 }
10326 else if(strstr(argv[1], "setApEnable")!=NULL) {
10327 BOOL enable = atoi(argv[3]);
10328 ret=wifi_setApEnable(index, enable);
10329 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10330 }
10331 else if(strstr(argv[1], "getApStatus")!=NULL) {
10332 char status[64];
10333 ret=wifi_getApStatus(index, status);
10334 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
10335 }
10336 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
10337 {
10338 wifi_getSSIDNameStatus(index,buf);
10339 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
10340 return 0;
10341 }
10342 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
10343 wifi_ssidTrafficStats2_t stats={0};
10344 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
10345 printf("%s %d: returns %d\n", argv[1], index, ret);
10346 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
10347 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
10348 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
10349 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
10350 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
10351 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
10352 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
10353 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
10354 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
10355 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
10356 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
10357 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
10358 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
10359 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
10360 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
10361 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
10362 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
10363 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
10364 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
10365 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
10366 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
10367 }
10368 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
10369 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
10370 UINT array_size=0;
10371 UINT i=0;
10372 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
10373 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10374 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
10375 printf(" neighbor %d:\n", i);
10376 printf(" ap_SSID =%s\n", pt->ap_SSID);
10377 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
10378 printf(" ap_Mode =%s\n", pt->ap_Mode);
10379 printf(" ap_Channel =%d\n", pt->ap_Channel);
10380 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
10381 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10382 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
10383 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
10384 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
10385 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
10386 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10387 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
10388 printf(" ap_Noise =%d\n", pt->ap_Noise);
10389 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
10390 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
10391 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
10392 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
10393 }
10394 if(neighbor_ap_array)
10395 free(neighbor_ap_array); //make sure to free the list
10396 }
10397 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
10398 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
10399 UINT array_size=0;
10400 UINT i=0;
10401 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
10402 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10403 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
10404 printf(" associated_dev %d:\n", i);
10405 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
10406 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
10407 printf(" cli_SNR =%d\n", pt->cli_SNR);
10408 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
10409 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
10410 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
10411 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
10412 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
10413 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
10414 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
10415 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
10416 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
10417 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
10418 }
10419 if(associated_dev_array)
10420 free(associated_dev_array); //make sure to free the list
10421 }
10422
10423 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
10424 {
10425#define MAX_ARRAY_SIZE 64
10426 int i, array_size;
10427 char *p, *ch_str;
10428 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
10429
10430 if(argc != 5)
10431 {
10432 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
10433 exit(-1);
10434 }
10435 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
10436
10437 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
10438 {
10439 strtok_r(ch_str, ",", &p);
10440 input_output_channelStats_array[i].ch_number = atoi(ch_str);
10441 }
10442 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
10443 if(!array_size)
10444 array_size=1;//Need to print current channel statistics
10445 for(i=0; i<array_size; i++)
10446 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
10447 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
10448 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
10449 input_output_channelStats_array[i].ch_number,\
10450 input_output_channelStats_array[i].ch_noise,\
10451 input_output_channelStats_array[i].ch_utilization_busy_rx,\
10452 input_output_channelStats_array[i].ch_utilization_busy_tx,\
10453 input_output_channelStats_array[i].ch_utilization_busy,\
10454 input_output_channelStats_array[i].ch_utilization_busy_ext,\
10455 input_output_channelStats_array[i].ch_utilization_total);
10456 }
10457
10458 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
10459 {
10460 if(argc <= 3 )
10461 {
10462 printf("Insufficient arguments \n");
10463 exit(-1);
10464 }
10465 char mac_addr[20] = {'\0'};
10466 wifi_device_t output_struct;
10467 int dev_index = atoi(argv[3]);
10468
10469 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
10470 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
10471 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);
10472 }
10473
10474 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
10475 {
10476 if (argc <= 3)
10477 {
10478 printf("Insufficient arguments\n");
10479 exit(-1);
10480 }
10481 char args[256];
10482 wifi_NeighborReport_t *neighborReports;
10483
10484 neighborReports = calloc(argc - 2, sizeof(neighborReports));
10485 if (!neighborReports)
10486 {
10487 printf("Failed to allocate memory");
10488 exit(-1);
10489 }
10490
10491 for (int i = 3; i < argc; ++i)
10492 {
10493 char *val;
10494 int j = 0;
10495 memset(args, 0, sizeof(args));
10496 strncpy(args, argv[i], sizeof(args));
10497 val = strtok(args, ";");
10498 while (val != NULL)
10499 {
10500 if (j == 0)
10501 {
10502 mac_addr_aton(neighborReports[i - 3].bssid, val);
10503 } else if (j == 1)
10504 {
10505 neighborReports[i - 3].info = strtol(val, NULL, 16);
10506 } else if (j == 2)
10507 {
10508 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
10509 } else if (j == 3)
10510 {
10511 neighborReports[i - 3].channel = strtol(val, NULL, 16);
10512 } else if (j == 4)
10513 {
10514 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
10515 } else {
10516 printf("Insufficient arguments]n\n");
10517 exit(-1);
10518 }
10519 val = strtok(NULL, ";");
10520 j++;
10521 }
10522 }
10523
10524 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
10525 if (ret != RETURN_OK)
10526 {
10527 printf("wifi_setNeighborReports ret = %d", ret);
10528 exit(-1);
10529 }
10530 }
10531 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
10532 {
10533 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
10534 printf("%s.\n", buf);
10535 else
10536 printf("Error returned\n");
10537 }
10538 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
10539 {
10540 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
10541 printf("%s.\n", buf);
10542 else
10543 printf("Error returned\n");
10544 }
10545 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
10546 {
10547 if (argc <= 2)
10548 {
10549 printf("Insufficient arguments\n");
10550 exit(-1);
10551 }
10552 char buf[64]= {'\0'};
10553 wifi_getRadioOperatingChannelBandwidth(index,buf);
10554 printf("Current bandwidth is %s \n",buf);
10555 return 0;
10556 }
10557 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
10558 {
10559 if (argc <= 5)
10560 {
10561 printf("Insufficient arguments\n");
10562 exit(-1);
10563 }
10564 UINT channel = atoi(argv[3]);
10565 UINT width = atoi(argv[4]);
10566 UINT beacon = atoi(argv[5]);
10567 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
10568 printf("Result = %d", ret);
10569 }
10570
10571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10572 return 0;
10573}
10574
10575#endif
10576
10577#ifdef WIFI_HAL_VERSION_3
10578
developer1e5aa162022-09-13 16:06:24 +080010579INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
10580{
10581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10582 if (bitMap & WIFI_BITRATE_1MBPS)
10583 strcat(BasicRate, "1,");
10584 if (bitMap & WIFI_BITRATE_2MBPS)
10585 strcat(BasicRate, "2,");
10586 if (bitMap & WIFI_BITRATE_5_5MBPS)
10587 strcat(BasicRate, "5.5,");
10588 if (bitMap & WIFI_BITRATE_6MBPS)
10589 strcat(BasicRate, "6,");
10590 if (bitMap & WIFI_BITRATE_9MBPS)
10591 strcat(BasicRate, "9,");
10592 if (bitMap & WIFI_BITRATE_11MBPS)
10593 strcat(BasicRate, "11,");
10594 if (bitMap & WIFI_BITRATE_12MBPS)
10595 strcat(BasicRate, "12,");
10596 if (bitMap & WIFI_BITRATE_18MBPS)
10597 strcat(BasicRate, "18,");
10598 if (bitMap & WIFI_BITRATE_24MBPS)
10599 strcat(BasicRate, "24,");
10600 if (bitMap & WIFI_BITRATE_36MBPS)
10601 strcat(BasicRate, "36,");
10602 if (bitMap & WIFI_BITRATE_48MBPS)
10603 strcat(BasicRate, "48,");
10604 if (bitMap & WIFI_BITRATE_54MBPS)
10605 strcat(BasicRate, "54,");
10606 if (strlen(BasicRate) != 0) // remove last comma
10607 BasicRate[strlen(BasicRate) - 1] = '\0';
10608 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10609 return RETURN_OK;
10610}
10611
10612INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
10613{
10614 UINT BitMap = 0;
10615 char *rate;
10616
10617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10618 rate = strtok(BasicRatesList, ",");
10619 while(rate != NULL)
10620 {
10621 if (strcmp(rate, "1") == 0)
10622 BitMap |= WIFI_BITRATE_1MBPS;
10623 else if (strcmp(rate, "2") == 0)
10624 BitMap |= WIFI_BITRATE_2MBPS;
10625 else if (strcmp(rate, "5.5") == 0)
10626 BitMap |= WIFI_BITRATE_5_5MBPS;
10627 else if (strcmp(rate, "6") == 0)
10628 BitMap |= WIFI_BITRATE_6MBPS;
10629 else if (strcmp(rate, "9") == 0)
10630 BitMap |= WIFI_BITRATE_9MBPS;
10631 else if (strcmp(rate, "11") == 0)
10632 BitMap |= WIFI_BITRATE_11MBPS;
10633 else if (strcmp(rate, "12") == 0)
10634 BitMap |= WIFI_BITRATE_12MBPS;
10635 else if (strcmp(rate, "18") == 0)
10636 BitMap |= WIFI_BITRATE_18MBPS;
10637 else if (strcmp(rate, "24") == 0)
10638 BitMap |= WIFI_BITRATE_24MBPS;
10639 else if (strcmp(rate, "36") == 0)
10640 BitMap |= WIFI_BITRATE_36MBPS;
10641 else if (strcmp(rate, "48") == 0)
10642 BitMap |= WIFI_BITRATE_48MBPS;
10643 else if (strcmp(rate, "54") == 0)
10644 BitMap |= WIFI_BITRATE_54MBPS;
10645 rate = strtok(NULL, ",");
10646 }
10647 *basicRateBitMap = BitMap;
10648 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10649 return RETURN_OK;
10650}
10651
10652// 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 +080010653INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
10654{
developer1e5aa162022-09-13 16:06:24 +080010655 char buf[128] = {0};
10656 char cmd[128] = {0};
10657 char config_file[64] = {0};
10658 int bandwidth;
10659 int set_mode;
10660 wifi_radio_operationParam_t current_param;
10661
10662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10663
10664 multiple_set = TRUE;
10665 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
10666 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
10667 return RETURN_ERR;
10668 }
10669 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
10670 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
10671 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
10672 return RETURN_ERR;
10673 }
10674 }
10675 if (current_param.channelWidth != operationParam->channelWidth || (current_param.channel != operationParam->channel && !operationParam->autoChannelEnabled)) {
10676 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
10677 bandwidth = 20;
10678 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
10679 bandwidth = 40;
10680 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
10681 bandwidth = 80;
10682 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
10683 bandwidth = 160;
10684 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
10685 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
10686 return RETURN_ERR;
10687 }
10688 }
10689 if (current_param.variant != operationParam->variant) {
10690 // Two different definition bit map, so need to check every bit.
10691 if (operationParam->variant & WIFI_80211_VARIANT_A)
10692 set_mode |= WIFI_MODE_A;
10693 if (operationParam->variant & WIFI_80211_VARIANT_B)
10694 set_mode |= WIFI_MODE_B;
10695 if (operationParam->variant & WIFI_80211_VARIANT_G)
10696 set_mode |= WIFI_MODE_G;
10697 if (operationParam->variant & WIFI_80211_VARIANT_N)
10698 set_mode |= WIFI_MODE_N;
10699 if (operationParam->variant & WIFI_80211_VARIANT_AC)
10700 set_mode |= WIFI_MODE_AC;
10701 if (operationParam->variant & WIFI_80211_VARIANT_AX)
10702 set_mode |= WIFI_MODE_AX;
10703 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
10704 memset(buf, 0, sizeof(buf));
10705 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
10706 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
10707 return RETURN_ERR;
10708 }
10709 }
10710 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
10711 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
10712 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
10713 return RETURN_ERR;
10714 }
10715 }
10716 if (current_param.beaconInterval != operationParam->beaconInterval) {
10717 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
10718 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
10719 return RETURN_ERR;
10720 }
10721 }
10722 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
10723 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
10724 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
10725 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
10726 return RETURN_ERR;
10727 }
10728 }
10729 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
10730 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
10731 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
10732 return RETURN_ERR;
10733 }
10734 }
10735 if (current_param.guardInterval != operationParam->guardInterval) {
10736 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
10737 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
10738 return RETURN_ERR;
10739 }
10740 }
10741 if (current_param.transmitPower != operationParam->transmitPower) {
10742 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
10743 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
10744 return RETURN_ERR;
10745 }
10746 }
10747 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
10748 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
10749 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
10750 return RETURN_ERR;
10751 }
10752 }
10753 if (current_param.obssCoex != operationParam->obssCoex) {
10754 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
10755 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
10756 return RETURN_ERR;
10757 }
10758 }
10759 if (current_param.stbcEnable != operationParam->stbcEnable) {
10760 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
10761 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
10762 return RETURN_ERR;
10763 }
10764 }
10765 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
10766 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
10767 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
10768 return RETURN_ERR;
10769 }
10770 }
10771
10772 // if enable is true, then restart the radio
10773 wifi_setRadioEnable(index, FALSE);
10774 if (operationParam->enable == TRUE)
10775 wifi_setRadioEnable(index, TRUE);
10776 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10777
developer06a01d92022-09-07 16:32:39 +080010778 return RETURN_OK;
10779}
10780
10781INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
10782{
developer1e5aa162022-09-13 16:06:24 +080010783 char band[64] = {0};
10784 char buf[256] = {0};
10785 char config_file[64] = {0};
10786 char cmd[128] = {0};
10787 int ret = RETURN_ERR;
10788 int mode = 0;
10789 ULONG channel = 0;
10790 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080010791
10792 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10793 printf("Entering %s index = %d\n", __func__, (int)index);
10794
developer1e5aa162022-09-13 16:06:24 +080010795 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
10796 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
10797 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080010798 {
developer1e5aa162022-09-13 16:06:24 +080010799 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080010800 return RETURN_ERR;
10801 }
10802 operationParam->enable = enabled;
10803
10804 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080010805 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080010806 {
developer1e5aa162022-09-13 16:06:24 +080010807 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080010808 return RETURN_ERR;
10809 }
10810
10811 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080010812 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080010813 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080010814 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080010815 else if (!strcmp(band, "6GHz"))
10816 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080010817 else
10818 {
developer1e5aa162022-09-13 16:06:24 +080010819 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080010820 band);
10821 }
10822
developer1e5aa162022-09-13 16:06:24 +080010823 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
10824 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
10825 operationParam->channel = 0;
10826 operationParam->autoChannelEnabled = TRUE;
10827 } else {
10828 operationParam->channel = strtol(buf, NULL, 10);
10829 operationParam->autoChannelEnabled = FALSE;
10830 }
10831
developer06a01d92022-09-07 16:32:39 +080010832 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080010833 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
10834 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
10835 return RETURN_ERR;
10836 }
developer06a01d92022-09-07 16:32:39 +080010837 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
10838 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
10839 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer1e5aa162022-09-13 16:06:24 +080010840 else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
10841 else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080010842 else
10843 {
developer1e5aa162022-09-13 16:06:24 +080010844 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
10845 return false;
developer06a01d92022-09-07 16:32:39 +080010846 }
10847
developer1e5aa162022-09-13 16:06:24 +080010848 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
10849 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
10850 return RETURN_ERR;
10851 }
10852 // Two different definition bit map, so need to check every bit.
10853 if (mode & WIFI_MODE_A)
10854 operationParam->variant |= WIFI_80211_VARIANT_A;
10855 if (mode & WIFI_MODE_B)
10856 operationParam->variant |= WIFI_80211_VARIANT_B;
10857 if (mode & WIFI_MODE_G)
10858 operationParam->variant |= WIFI_80211_VARIANT_G;
10859 if (mode & WIFI_MODE_N)
10860 operationParam->variant |= WIFI_80211_VARIANT_N;
10861 if (mode & WIFI_MODE_AC)
10862 operationParam->variant |= WIFI_80211_VARIANT_AC;
10863 if (mode & WIFI_MODE_AX)
10864 operationParam->variant |= WIFI_80211_VARIANT_AX;
10865 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
10866 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
10867 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010868 }
developer1e5aa162022-09-13 16:06:24 +080010869 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
10870 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
10871 return RETURN_ERR;
10872 }
10873 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
10874 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
10875 return RETURN_ERR;
10876 }
developer06a01d92022-09-07 16:32:39 +080010877
developer1e5aa162022-09-13 16:06:24 +080010878 memset(buf, 0, sizeof(buf));
10879 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
10880 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
10881 return RETURN_ERR;
10882 }
10883 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
10884
10885 memset(buf, 0, sizeof(buf));
10886 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
10887 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
10888 return RETURN_ERR;
10889 }
10890 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
10891
10892 memset(buf, 0, sizeof(buf));
10893 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
10894 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
10895
10896 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
10897 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
10898 return RETURN_ERR;
10899 }
10900 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
10901 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
10902 return RETURN_ERR;
10903 }
10904
10905 memset(buf, 0, sizeof(buf));
10906 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
10907 if (strcmp(buf, "-1") == 0) {
10908 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
10909 operationParam->ctsProtection = FALSE;
10910 } else {
10911 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
10912 operationParam->ctsProtection = TRUE;
10913 }
10914
10915 memset(buf, 0, sizeof(buf));
10916 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
10917 if (strcmp(buf, "0") == 0)
10918 operationParam->obssCoex = FALSE;
10919 else
10920 operationParam->obssCoex = TRUE;
10921
10922 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
10923 _syscmd(cmd, buf, sizeof(buf));
10924 if (strlen(buf) != 0)
10925 operationParam->stbcEnable = TRUE;
10926 else
10927 operationParam->stbcEnable = FALSE;
10928
10929 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
10930 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
10931 return RETURN_ERR;
10932 }
10933
10934 // Below value is hardcoded
10935
10936 operationParam->numSecondaryChannels = 0;
10937 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
10938 operationParam->channelSecondary[i] = 0;
10939 }
10940 operationParam->csa_beacon_count = 15;
10941 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080010942
10943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10944 return RETURN_OK;
10945}
10946
10947static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
10948{
10949 if (radioIndex != 0 && radioIndex != 1)
10950 {
10951 printf("%s: Wrong radio index (%d)\n", __func__, index);
10952 return -1;
10953 }
10954
10955 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
10956 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
10957
10958 return (arrayIndex * 2) + radioIndex;
10959}
10960
10961INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
10962{
10963 INT ret;
10964 int i;
10965 BOOL enabled = false;
10966 char buf[256];
10967 wifi_secur_list *secur_item;
10968 int vap_index;
10969 INT mode;
10970 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
10971
10972 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10973 printf("Entering %s index = %d\n", __func__, (int)index);
10974
10975 map->vap_array[index].radio_index = index;
10976 for (i = 0; i < 5; i++)
10977 {
10978 vap_index = array_index_to_vap_index(index, i);
10979 if (vap_index < 0)
10980 {
10981 return RETURN_ERR;
10982 }
10983
10984 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
10985
10986 map->vap_array[i].vap_index = vap_index;
10987
10988 memset(buf, 0, sizeof(buf));
10989 wifi_getApName(vap_index, buf); // XXX: error handling
10990 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
10991
10992 ret = wifi_getSSIDEnable(vap_index, &enabled);
10993 if (ret != RETURN_OK)
10994 {
10995 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
10996 return RETURN_ERR;
10997 }
10998 map->vap_array[i].u.bss_info.enabled = enabled;
10999
11000 memset(buf, 0, sizeof(buf));
11001 wifi_getBaseBSSID(vap_index, buf);
11002 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11003 &map->vap_array[i].u.bss_info.bssid[0],
11004 &map->vap_array[i].u.bss_info.bssid[1],
11005 &map->vap_array[i].u.bss_info.bssid[2],
11006 &map->vap_array[i].u.bss_info.bssid[3],
11007 &map->vap_array[i].u.bss_info.bssid[4],
11008 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
11009
11010 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
11011 map->vap_array[i].u.bss_info.showSsid = enabled;
11012
11013 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
11014 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
11015 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
11016
11017 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11018 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
11019
11020 memset(buf, 0, sizeof(buf));
11021 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
11022 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
11023
11024 wifi_getApSecurityModeEnabled(vap_index, buf);
11025
11026 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
11027 {
11028 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
11029 return RETURN_ERR;
11030 }
11031 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
11032
11033 memset(buf, 0, sizeof(buf));
11034 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
11035 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);
11036
11037 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
11038 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
11039
11040 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
11041 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
11042
11043 wifi_getApIsolationEnable(vap_index, &enabled);
11044 map->vap_array[i].u.bss_info.isolation = enabled;
11045 }
11046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11047 return RETURN_OK;
11048}
11049
11050INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11051{
11052 unsigned int i;
11053 wifi_vap_info_t *vap_info = NULL;
11054 int acl_mode;
11055 char *sec_str = NULL;
11056
11057 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11058 printf("Entering %s index = %d\n", __func__, (int)index);
11059 for (i = 0; i < map->num_vaps; i++)
11060 {
11061 vap_info = &map->vap_array[i];
11062 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11063
11064 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11065 else
11066 {
11067 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11068 else acl_mode = 1;
11069 }
11070 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11071 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11072 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11073
11074 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11075 if (sec_str)
11076 {
11077 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11078 }
11079 else
11080 {
11081 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11082 }
11083
11084 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11085 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11086
11087 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11088 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11089
11090 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11091
11092 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11093 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11094 }
11095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11096 return RETURN_OK;
11097}
11098
11099int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11100{
11101 char *token, *next;
11102 const char s[2] = ",";
11103 int count =0;
11104
11105 /* get the first token */
11106 token = strtok_r(pchannels, s, &next);
11107
11108 /* walk through other tokens */
11109 while( token != NULL && count < MAX_CHANNELS) {
11110 chlistptr->channels_list[count++] = atoi(token);
11111 token = strtok_r(NULL, s, &next);
11112 }
11113
11114 return count;
11115}
11116
11117static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11118{
11119 INT status;
11120 wifi_channels_list_t *chlistp;
11121 CHAR output_string[64];
11122 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011123 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011124
11125 if(rcap == NULL)
11126 {
11127 return RETURN_ERR;
11128 }
11129
11130 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011131 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011132
developer1e5aa162022-09-13 16:06:24 +080011133 if (band == band_2_4)
11134 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11135 else if (band == band_5)
11136 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11137 else if (band == band_6)
11138 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011139
11140 chlistp = &(rcap->channel_list[0]);
11141 memset(pchannels, 0, sizeof(pchannels));
11142
11143 /* possible number of radio channels */
11144 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11145 {
11146 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11147 }
11148 /* Number of channels and list*/
11149 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11150
11151 /* autoChannelSupported */
11152 /* always ON with wifi_getRadioAutoChannelSupported */
11153 rcap->autoChannelSupported = TRUE;
11154
11155 /* DCSSupported */
11156 /* always ON with wifi_getRadioDCSSupported */
11157 rcap->DCSSupported = TRUE;
11158
11159 /* zeroDFSSupported - TBD */
11160 rcap->zeroDFSSupported = FALSE;
11161
11162 /* Supported Country List*/
11163 memset(output_string, 0, sizeof(output_string));
11164 status = wifi_getRadioCountryCode(radioIndex, output_string);
11165 if( status != 0 ) {
11166 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11167 return RETURN_ERR;
11168 } else {
11169 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11170 }
11171 if(!strcmp(output_string,"US")){
11172 rcap->countrySupported[0] = wifi_countrycode_US;
11173 rcap->countrySupported[1] = wifi_countrycode_CA;
11174 } else if (!strcmp(output_string,"CA")) {
11175 rcap->countrySupported[0] = wifi_countrycode_CA;
11176 rcap->countrySupported[1] = wifi_countrycode_US;
11177 } else {
11178 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11179 }
11180
11181 rcap->numcountrySupported = 2;
11182
11183 /* csi */
11184 rcap->csi.maxDevices = 8;
11185 rcap->csi.soudingFrameSupported = TRUE;
11186
11187 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
11188
11189 /* channelWidth - all supported bandwidths */
11190 int i=0;
11191 rcap->channelWidth[i] = 0;
11192 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11193 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11194 WIFI_CHANNELBANDWIDTH_40MHZ);
11195
11196 }
developer1e5aa162022-09-13 16:06:24 +080011197 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080011198 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11199 WIFI_CHANNELBANDWIDTH_40MHZ |
11200 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
11201 }
11202
11203
11204 /* mode - all supported variants */
11205 // rcap->mode[i] = WIFI_80211_VARIANT_H;
11206 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011207 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 +080011208 }
11209 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011210 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
11211 }
11212 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
11213 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011214 }
11215 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
11216 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
11217
11218 /* supportedBitRate - all supported bitrates */
11219 rcap->supportedBitRate[i] = 0;
11220 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11221 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11222 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
11223 }
developer1e5aa162022-09-13 16:06:24 +080011224 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080011225 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11226 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
11227 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
11228 }
11229
11230
11231 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
11232 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
11233 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
11234 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
11235 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
11236 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
11237 rcap->cipherSupported = 0;
11238 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
11239 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
11240
11241 return RETURN_OK;
11242}
11243
11244INT wifi_getHalCapability(wifi_hal_capability_t *cap)
11245{
11246 INT status, radioIndex;
11247 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
11248 int iter = 0;
11249 unsigned int j;
11250 wifi_interface_name_idex_map_t *iface_info;
11251
11252 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11253
11254 memset(cap, 0, sizeof(wifi_hal_capability_t));
11255
11256 /* version */
11257 cap->version.major = WIFI_HAL_MAJOR_VERSION;
11258 cap->version.minor = WIFI_HAL_MINOR_VERSION;
11259
11260 /* number of radios platform property */
11261 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
11262 _syscmd(cmd, output, sizeof(output));
11263 cap->wifi_prop.numRadios = atoi(output);
11264
11265 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
11266 {
11267 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
11268 if (status != 0) {
11269 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
11270 return RETURN_ERR;
11271 }
11272
11273 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
11274 {
11275 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
11276 {
11277 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
11278 return RETURN_ERR;
11279 }
11280 iface_info = &cap->wifi_prop.interface_map[iter];
11281 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
11282 iface_info->rdk_radio_index = radioIndex;
11283 memset(output, 0, sizeof(output));
11284 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
11285 {
11286 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
11287 }
11288 // TODO: bridge name
11289 // TODO: vlan id
11290 // TODO: primary
11291 iface_info->index = array_index_to_vap_index(radioIndex, j);
11292 memset(output, 0, sizeof(output));
11293 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
11294 {
11295 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
11296 }
11297 iter++;
11298 }
11299 }
11300
11301 cap->BandSteeringSupported = FALSE;
11302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11303 return RETURN_OK;
11304}
11305
11306INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
11307{
11308 //TODO
11309 return RETURN_OK;
11310}
11311
11312INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
11313{
11314 //TODO
11315 return RETURN_OK;
11316}
11317
11318#endif /* WIFI_HAL_VERSION_3 */
11319
11320#ifdef WIFI_HAL_VERSION_3_PHASE2
11321INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
11322{
11323 return RETURN_OK;
11324}
11325#else
11326INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
11327{
11328 char cmd[128];
11329 BOOL status = false;
11330
11331 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
11332 return RETURN_ERR;
11333
11334 output_buf[0] = '\0';
11335
11336 wifi_getApEnable(ap_index,&status);
11337 if (!status)
11338 return RETURN_OK;
11339
11340 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
11341 _syscmd(cmd, output_buf, output_buf_size);
11342
11343 return RETURN_OK;
11344}
11345#endif
developer2f513ab2022-09-13 14:26:06 +080011346
11347INT wifi_getProxyArp(INT apIndex, BOOL *enable)
11348{
11349 char output[16]={'\0'};
11350 char config_file[MAX_BUF_SIZE] = {0};
11351
11352 if (!enable)
11353 return RETURN_ERR;
11354
11355 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
11356 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
11357
11358 if (strlen(output) == 0)
11359 *enable = FALSE;
11360 else if (strncmp(output, "1", 1) == 0)
11361 *enable = TRUE;
11362 else
11363 *enable = FALSE;
11364
11365 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
11366 return RETURN_OK;
11367}
developer2d9c30f2022-09-13 15:06:14 +080011368
11369INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
11370{
11371 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
11372 return RETURN_ERR;
11373 *output_enable=TRUE;
11374 return RETURN_OK;
11375}