blob: 458be6f0c668bbcccb74910519bbb2c01964e9ed [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
66#define MAX_BUF_SIZE 128
67#define MAX_CMD_SIZE 1024
68#define MAX_POSSIBLE_CHANNEL_STRING_BUF 512
69#define IF_NAME_SIZE 50
70#define CONFIG_PREFIX "/nvram/hostapd"
71#define ACL_PREFIX "/tmp/hostapd-acl"
developer10adcc12022-09-13 14:39:17 +080072#define DENY_PREFIX "/tmp/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080073//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
74#define SOCK_PREFIX "/var/run/hostapd/wifi"
75#define VAP_STATUS_FILE "/tmp/vap-status"
developera3c68b92022-09-13 15:27:29 +080076#define ESSID_FILE "/tmp/essid"
developer454b9462022-09-13 15:29:16 +080077#define GUARD_INTERVAL_FILE "/tmp/guard-interval"
developera748dcf2022-09-13 15:56:48 +080078#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080079#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080080#define VLAN_FILE "/nvram/hostapd.vlan"
developer8d583982022-09-20 11:28:22 +080081#define PSK_FILE "/tmp/hostapd"
developer2de97692022-09-26 14:00:03 +080082#define CHAIN_MASK_FILE "/tmp/chain_mask"
developer54e6b9f2022-09-28 14:41:20 +080083#define AMSDU_FILE "/tmp/AMSDU"
developerf49437e2022-09-29 19:58:21 +080084#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080085#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080086
developer06a01d92022-09-07 16:32:39 +080087#define DRIVER_2GHZ "ath9k"
88#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080089#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080090
91/*
92 MAX_APS - Number of all AP available in system
93 2x Home AP
94 2x Backhaul AP
95 2x Guest AP
96 2x Secure Onboard AP
97 2x Service AP
98
99*/
100#define MAX_APS 10
101#define NUMBER_OF_RADIOS 2
102
103#ifndef AP_PREFIX
104#define AP_PREFIX "wifi"
105#endif
106
107#ifndef RADIO_PREFIX
108#define RADIO_PREFIX "wlan"
109#endif
110
111#define MAX_BUF_SIZE 128
112#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800113#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800114
115//Uncomment to enable debug logs
116//#define WIFI_DEBUG
117
118#ifdef WIFI_DEBUG
119#define wifi_dbg_printf printf
120#define WIFI_ENTRY_EXIT_DEBUG printf
121#else
122#define wifi_dbg_printf(format, args...) printf("")
123#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
124#endif
125
126#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
127#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
128#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
129#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
130#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
131#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
132#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
133#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
134#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
135#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
136
137#define HOSTAPD_HT_CAPAB_20 "[SHORT-GI-20]"
138#define HOSTAPD_HT_CAPAB_40 "[SHORT-GI-20][SHORT-GI-40]"
developer3cc0f2e2022-09-15 18:25:39 +0800139#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800140
141#define BW_FNAME "/nvram/bw_file.txt"
142
143#define PS_MAX_TID 16
144
145static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
146 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
148 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
149 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
151 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
153 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
154 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
155 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
156 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
157 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
158 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
159 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
160 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
161 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
162};
163
164typedef unsigned long long u64;
165
166/* Enum to define WiFi Bands */
167typedef enum
168{
169 band_invalid = -1,
170 band_2_4 = 0,
171 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800172 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800173} wifi_band;
174
developerdb744382022-09-13 15:34:54 +0800175typedef enum {
176 WIFI_MODE_A = 0x01,
177 WIFI_MODE_B = 0x02,
178 WIFI_MODE_G = 0x04,
179 WIFI_MODE_N = 0x08,
180 WIFI_MODE_AC = 0x10,
181 WIFI_MODE_AX = 0x20,
182} wifi_ieee80211_Mode;
183
developer06a01d92022-09-07 16:32:39 +0800184#ifdef WIFI_HAL_VERSION_3
185
186// Return number of elements in array
187#ifndef ARRAY_SIZE
188#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
189#endif /* ARRAY_SIZE */
190
191#ifndef ARRAY_AND_SIZE
192#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
193#endif /* ARRAY_AND_SIZE */
194
195#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
196
197typedef struct {
198 int32_t value;
199 int32_t param;
200 intptr_t key;
201 intptr_t data;
202} wifi_secur_list;
203
204wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
205wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
206char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800207static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800208
209static wifi_secur_list map_security[] =
210{
211 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
212 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
213 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
219 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
220};
221
222wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
223{
224 wifi_secur_list *item;
225 int i;
226
227 for (item = list,i = 0;i < list_sz; item++, i++) {
228 if ((int)(item->key) == key) {
229 return item;
230 }
231 }
232
233 return NULL;
234}
235
236char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
237{
238 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
239
240 if (!item) {
241 return "";
242 }
243
244 return (char *)(item->data);
245}
246
247wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
248{
249 wifi_secur_list *item;
250 int i;
251
252 for (item = list,i = 0;i < list_sz; item++, i++) {
253 if (strcmp((char *)(item->data), str) == 0) {
254 return item;
255 }
256 }
257
258 return NULL;
259}
260#endif /* WIFI_HAL_VERSION_3 */
261
262#ifdef HAL_NETLINK_IMPL
263typedef struct {
264 int id;
265 struct nl_sock* socket;
266 struct nl_cb* cb;
267} Netlink;
268
269static int mac_addr_aton(unsigned char *mac_addr, char *arg)
270{
271 unsigned int mac_addr_int[6]={};
272 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);
273 mac_addr[0] = mac_addr_int[0];
274 mac_addr[1] = mac_addr_int[1];
275 mac_addr[2] = mac_addr_int[2];
276 mac_addr[3] = mac_addr_int[3];
277 mac_addr[4] = mac_addr_int[4];
278 mac_addr[5] = mac_addr_int[5];
279 return 0;
280}
281
282static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
283{
284 unsigned int mac_addr_int[6]={};
285 mac_addr_int[0] = arg[0];
286 mac_addr_int[1] = arg[1];
287 mac_addr_int[2] = arg[2];
288 mac_addr_int[3] = arg[3];
289 mac_addr_int[4] = arg[4];
290 mac_addr_int[5] = arg[5];
291 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]);
292 return;
293}
294
295static int ieee80211_frequency_to_channel(int freq)
296{
297 if (freq == 2484)
298 return 14;
299 else if (freq < 2484)
300 return (freq - 2407) / 5;
301 else if (freq >= 4910 && freq <= 4980)
302 return (freq - 4000) / 5;
303 else if (freq <= 45000)
304 return (freq - 5000) / 5;
305 else if (freq >= 58320 && freq <= 64800)
306 return (freq - 56160) / 2160;
307 else
308 return 0;
309}
310
311static int initSock80211(Netlink* nl) {
312 nl->socket = nl_socket_alloc();
313 if (!nl->socket) {
314 fprintf(stderr, "Failing to allocate the sock\n");
315 return -ENOMEM;
316 }
317
318 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
319
320 if (genl_connect(nl->socket)) {
321 fprintf(stderr, "Failed to connect\n");
322 nl_close(nl->socket);
323 nl_socket_free(nl->socket);
324 return -ENOLINK;
325 }
326
327 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
328 if (nl->id< 0) {
329 fprintf(stderr, "interface not found.\n");
330 nl_close(nl->socket);
331 nl_socket_free(nl->socket);
332 return -ENOENT;
333 }
334
335 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
336 if ((!nl->cb)) {
337 fprintf(stderr, "Failed to allocate netlink callback.\n");
338 nl_close(nl->socket);
339 nl_socket_free(nl->socket);
340 return ENOMEM;
341 }
342
343 return nl->id;
344}
345
346static int nlfree(Netlink *nl)
347{
348 nl_cb_put(nl->cb);
349 nl_close(nl->socket);
350 nl_socket_free(nl->socket);
351 return 0;
352}
353
354static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
355 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
356 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
357 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
358};
359
360static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
361};
362
363static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
364};
365
366typedef struct _wifi_channelStats_loc {
367 INT array_size;
368 INT ch_number;
369 BOOL ch_in_pool;
370 INT ch_noise;
371 BOOL ch_radar_noise;
372 INT ch_max_80211_rssi;
373 INT ch_non_80211_noise;
374 INT ch_utilization;
375 ULLONG ch_utilization_total;
376 ULLONG ch_utilization_busy;
377 ULLONG ch_utilization_busy_tx;
378 ULLONG ch_utilization_busy_rx;
379 ULLONG ch_utilization_busy_self;
380 ULLONG ch_utilization_busy_ext;
381} wifi_channelStats_t_loc;
382
383typedef struct wifi_device_info {
384 INT wifi_devIndex;
385 UCHAR wifi_devMacAddress[6];
386 CHAR wifi_devIPAddress[64];
387 BOOL wifi_devAssociatedDeviceAuthentiationState;
388 INT wifi_devSignalStrength;
389 INT wifi_devTxRate;
390 INT wifi_devRxRate;
391} wifi_device_info_t;
392
393#endif
394
395//For 5g Alias Interfaces
396static BOOL priv_flag = TRUE;
397static BOOL pub_flag = TRUE;
398static BOOL Radio_flag = TRUE;
399//wifi_setApBeaconRate(1, beaconRate);
400
developer1e5aa162022-09-13 16:06:24 +0800401BOOL multiple_set = FALSE;
402
developer06a01d92022-09-07 16:32:39 +0800403struct params
404{
405 char * name;
406 char * value;
407};
408
409static int _syscmd(char *cmd, char *retBuf, int retBufSize)
410{
411 FILE *f;
412 char *ptr = retBuf;
413 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
414
415 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
416 if((f = popen(cmd, "r")) == NULL) {
417 fprintf(stderr,"\npopen %s error\n", cmd);
418 return RETURN_ERR;
419 }
420
421 while(!feof(f))
422 {
423 *ptr = 0;
424 if(bufSize>=128) {
425 bufbytes=128;
426 } else {
427 bufbytes=bufSize-1;
428 }
429
430 fgets(ptr,bufbytes,f);
431 readbytes=strlen(ptr);
432
433 if(!readbytes)
434 break;
435
436 bufSize-=readbytes;
437 ptr += readbytes;
438 }
439 cmd_ret = pclose(f);
440 retBuf[retBufSize-1]=0;
441 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
442
443 return cmd_ret >> 8;
444}
445
developerc707e972022-09-13 15:38:02 +0800446wifi_band wifi_index_to_band(int apIndex)
447{
448 char cmd[128] = {0};
449 char buf[64] = {0};
450 int freq = 0;
451 wifi_band band = band_invalid;
452
453 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
454 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
455 _syscmd(cmd, buf, sizeof(buf));
456 freq = strtol(buf, NULL, 10);
457 if (freq > 2401 && freq < 2495)
458 band = band_2_4;
459 else if (freq > 5160 && freq < 5915)
460 band = band_5;
461 else if (freq > 5955 && freq < 7125)
462 band = band_6;
463
464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
465 return band;
466}
467
developer06a01d92022-09-07 16:32:39 +0800468static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
469{
470 char cmd[MAX_CMD_SIZE]={'\0'};
471 char buf[MAX_BUF_SIZE]={'\0'};
472 int ret = 0;
473
474 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
475 ret = _syscmd(cmd, buf, sizeof(buf));
476 if ((ret != 0) && (strlen(buf) == 0))
477 return -1;
478 snprintf(output, output_size, "%s", buf);
479
480 return 0;
481}
482
483static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
484{
485 char cmd[MAX_CMD_SIZE]={'\0'};
486 char buf[MAX_BUF_SIZE]={'\0'};
487
488 for(int i=0;i<item_count;i++)
489 {
490 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
491 if (strlen(buf) == 0) //Insert
492 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
493 else //Update
494 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
495 if(_syscmd(cmd, buf, sizeof(buf)))
496 return -1;
497 }
498
499 return 0;
500}
501
502static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
503{
developer1e5aa162022-09-13 16:06:24 +0800504 if (multiple_set == TRUE)
505 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800506 char cmd[MAX_CMD_SIZE]="", output[32]="";
507 FILE *fp;
508 int i;
509 //NOTE RELOAD should be done in ApplySSIDSettings
510
511 for(i=0; i<item_count; i++, list++)
512 {
513 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
514 if((fp = popen(cmd, "r"))==NULL)
515 {
516 perror("popen failed");
517 return -1;
518 }
519 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
520 {
521 pclose(fp);
522 perror("fgets failed");
523 return -1;
524 }
525 pclose(fp);
526 }
527 return 0;
528}
529
530static int wifi_reloadAp(int apIndex)
531{
developer1e5aa162022-09-13 16:06:24 +0800532 if (multiple_set == TRUE)
533 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800534 char cmd[MAX_CMD_SIZE]="";
535 char buf[MAX_BUF_SIZE]="";
536
537 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
538 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
539 return RETURN_ERR;
540
541 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
542 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
543 return RETURN_ERR;
544
545 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
546 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
547 return RETURN_ERR;
548
549 return RETURN_OK;
550}
551
552
553//For Getting Current Interface Name from corresponding hostapd configuration
554void GetInterfaceName(char *interface_name, char *conf_file)
555{
556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
557 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
559}
560
561INT File_Reading(CHAR *file, char *Value)
562{
563 FILE *fp = NULL;
564 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
565 int count = 0;
566
567 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
568 fp = popen(file,"r");
569 if(fp == NULL)
570 return RETURN_ERR;
571
572 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
573 {
574 for(count=0;buf[count]!='\n';count++)
575 copy_buf[count]=buf[count];
576 copy_buf[count]='\0';
577 }
578 strcpy(Value,copy_buf);
579 pclose(fp);
580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
581
582 return RETURN_OK;
583}
584
585void wifi_RestartHostapd_2G()
586{
587 int Public2GApIndex = 4;
588
589 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
590 wifi_setApEnable(Public2GApIndex, FALSE);
591 wifi_setApEnable(Public2GApIndex, TRUE);
592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
593}
594
595void wifi_RestartHostapd_5G()
596{
597 int Public5GApIndex = 5;
598
599 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
600 wifi_setApEnable(Public5GApIndex, FALSE);
601 wifi_setApEnable(Public5GApIndex, TRUE);
602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
603}
604
605void wifi_RestartPrivateWifi_2G()
606{
607 int PrivateApIndex = 0;
608
609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
610 wifi_setApEnable(PrivateApIndex, FALSE);
611 wifi_setApEnable(PrivateApIndex, TRUE);
612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
613}
614
615void wifi_RestartPrivateWifi_5G()
616{
617 int Private5GApIndex = 1;
618
619 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
620 wifi_setApEnable(Private5GApIndex, FALSE);
621 wifi_setApEnable(Private5GApIndex, TRUE);
622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
623}
624
625static int writeBandWidth(int radioIndex,char *bw_value)
626{
627 char buf[MAX_BUF_SIZE];
628 char cmd[MAX_CMD_SIZE];
629
630 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
631 if(_syscmd(cmd, buf, sizeof(buf)))
632 {
633 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
634 _syscmd(cmd, buf, sizeof(buf));
635 return RETURN_OK;
636 }
637
638 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
639 _syscmd(cmd,buf,sizeof(buf));
640 return RETURN_OK;
641}
642
643static int readBandWidth(int radioIndex,char *bw_value)
644{
645 char buf[MAX_BUF_SIZE];
646 char cmd[MAX_CMD_SIZE];
647 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
648 _syscmd(cmd,buf,sizeof(buf));
649 if(NULL!=strstr(buf,"20MHz"))
650 {
651 strcpy(bw_value,"20MHz");
652 }
653 else if(NULL!=strstr(buf,"40MHz"))
654 {
655 strcpy(bw_value,"40MHz");
656 }
657 else if(NULL!=strstr(buf,"80MHz"))
658 {
659 strcpy(bw_value,"80MHz");
660 }
661 else
662 {
663 return RETURN_ERR;
664 }
665 return RETURN_OK;
666}
667
developer39a5efb2022-09-13 16:09:06 +0800668INT wifi_getMaxRadioNumber(INT *max_radio_num)
669{
670 char cmd[64] = {0};
671 char buf[4] = {0};
672
673 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
674
675 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
676 _syscmd(cmd, buf, sizeof(buf));
677 *max_radio_num = strtoul(buf, NULL, 10);
678
679 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
680
681 return RETURN_OK;
682}
683
developer5f222492022-09-13 15:21:52 +0800684// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800685INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
686{
developer5f222492022-09-13 15:21:52 +0800687 struct params params={'\0'};
688 char config_file[MAX_BUF_SIZE] = {0};
689 char buf[MAX_BUF_SIZE] = {'\0'};
690
691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
692 if (strlen (beaconRate) < 5)
693 return RETURN_ERR;
694 // Copy the numeric value
695 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
696 buf[strlen(beaconRate) - 4] = '\0';
697
698 params.name = "beacon_rate";
699 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
700 if (strncmp(buf, "5.5", 3) == 0) {
701 snprintf(buf, sizeof(buf), "55");
702 params.value = buf;
703 } else {
704 strcat(buf, "0");
705 params.value = buf;
706 }
707
708 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
709 wifi_hostapdWrite(config_file, &params, 1);
710 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
711 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
712
713 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800714}
715
716INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
717{
developer5f222492022-09-13 15:21:52 +0800718 char config_file[MAX_BUF_SIZE] = {'\0'};
719 char temp_output[MAX_BUF_SIZE] = {'\0'};
720 char buf[MAX_BUF_SIZE] = {'\0'};
721 float rate = 0;
722
723 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
724 if (NULL == beaconRate)
725 return RETURN_ERR;
726
727 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
728 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
729 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
730 if(strlen(buf) > 0) {
731 rate = atof(buf)/10;
732 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
733 } else {
734 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
735 }
736 strncpy(beaconRate, temp_output, sizeof(temp_output));
737 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
738
739 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800740}
741
742INT wifi_setLED(INT radioIndex, BOOL enable)
743{
744 return 0;
745}
746INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
747{
748 return RETURN_OK;
749}
750/**********************************************************************************
751 *
752 * Wifi Subsystem level function prototypes
753 *
754**********************************************************************************/
755//---------------------------------------------------------------------------------------------------
756//Wifi system api
757//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
758INT wifi_getHalVersion(CHAR *output_string) //RDKB
759{
760 if(!output_string)
761 return RETURN_ERR;
762 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
763
764 return RETURN_OK;
765}
766
767
768/* wifi_factoryReset() function */
769/**
770* @description Clears internal variables to implement a factory reset of the Wi-Fi
771* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
772*
773* @param None
774*
775* @return The status of the operation.
776* @retval RETURN_OK if successful.
777* @retval RETURN_ERR if any error is detected
778*
779* @execution Synchronous
780* @sideeffect None
781*
782* @note This function must not suspend and must not invoke any blocking system
783* calls. It should probably just send a message to a driver event handler task.
784*
785*/
786INT wifi_factoryReset()
787{
788 char cmd[128];
789
790 /*delete running hostapd conf files*/
791 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
792 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
793 system(cmd);
794 system("systemctl restart hostapd.service");
795
796 return RETURN_OK;
797}
798
799/* wifi_factoryResetRadios() function */
800/**
801* @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.
802*
803* @param None
804* @return The status of the operation
805* @retval RETURN_OK if successful
806* @retval RETURN_ERR if any error is detected
807*
808* @execution Synchronous
809*
810* @sideeffect None
811*
812* @note This function must not suspend and must not invoke any blocking system
813* calls. It should probably just send a message to a driver event handler task.
814*
815*/
816INT wifi_factoryResetRadios()
817{
818 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
819 return RETURN_OK;
820
821 return RETURN_ERR;
822}
823
824
825/* wifi_factoryResetRadio() function */
826/**
827* @description Restore selected radio parameters without touching access point parameters
828*
829* @param radioIndex - Index of Wi-Fi Radio channel
830*
831* @return The status of the operation.
832* @retval RETURN_OK if successful.
833* @retval RETURN_ERR if any error is detected
834*
835* @execution Synchronous.
836* @sideeffect None.
837*
838* @note This function must not suspend and must not invoke any blocking system
839* calls. It should probably just send a message to a driver event handler task.
840*
841*/
842INT wifi_factoryResetRadio(int radioIndex) //RDKB
843{
developer5ff7f5f2022-09-13 15:12:16 +0800844 system("systemctl stop hostapd.service");
845
developer06a01d92022-09-07 16:32:39 +0800846 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
847 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800848 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800849 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800850 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800851 else
852 return RETURN_ERR;
853
developer5ff7f5f2022-09-13 15:12:16 +0800854 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
856 return RETURN_OK;
857}
858
859/* wifi_initRadio() function */
860/**
861* Description: This function call initializes the specified radio.
862* Implementation specifics may dictate the functionality since
863* different hardware implementations may have different initilization requirements.
864* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
865*
866* @return The status of the operation.
867* @retval RETURN_OK if successful.
868* @retval RETURN_ERR if any error is detected
869*
870* @execution Synchronous.
871* @sideeffect None.
872*
873* @note This function must not suspend and must not invoke any blocking system
874* calls. It should probably just send a message to a driver event handler task.
875*
876*/
877INT wifi_initRadio(INT radioIndex)
878{
879 //TODO: Initializes the wifi subsystem (for specified radio)
880 return RETURN_OK;
881}
882void macfilter_init()
883{
884 char count[4]={'\0'};
885 char buf[253]={'\0'};
886 char tmp[19]={'\0'};
887 int dev_count,block,mac_entry=0;
888 char res[4]={'\0'};
889 char acl_file_path[64] = {'\0'};
890 FILE *fp = NULL;
891 int index=0;
892 char iface[10]={'\0'};
893 char config_file[MAX_BUF_SIZE] = {0};
894
895
896 sprintf(acl_file_path,"/tmp/mac_filter.sh");
897
898 fp=fopen(acl_file_path,"w+");
899 sprintf(buf,"#!/bin/sh \n");
900 fprintf(fp,"%s\n",buf);
901
902 system("chmod 0777 /tmp/mac_filter.sh");
903
904 for(index=0;index<=1;index++)
905 {
906 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
907 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
908 sprintf(buf,"syscfg get %dcountfilter",index);
909 _syscmd(buf,count,sizeof(count));
910 mac_entry=atoi(count);
911
912 sprintf(buf,"syscfg get %dblockall",index);
913 _syscmd(buf,res,sizeof(res));
914 block = atoi(res);
915
916 //Allow only those macs mentioned in ACL
917 if(block==1)
918 {
919 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
920 fprintf(fp,"%s\n",buf);
921 for(dev_count=1;dev_count<=mac_entry;dev_count++)
922 {
923 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
924 _syscmd(buf,tmp,sizeof(tmp));
925 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
926 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
927 fprintf(fp,"%s\n",buf);
928 }
929 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
930 fprintf(fp,"%s\n",buf);
931 }
932
933 //Block all the macs mentioned in ACL
934 else if(block==2)
935 {
936 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
937 fprintf(fp,"%s\n",buf);
938
939 for(dev_count=1;dev_count<=mac_entry;dev_count++)
940 {
941 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
942 _syscmd(buf,tmp,sizeof(tmp));
943 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
944 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
945 fprintf(fp,"%s\n",buf);
946 }
947 }
948 }
949 fclose(fp);
950}
951
952// Initializes the wifi subsystem (all radios)
953INT wifi_init() //RDKB
954{
955 char interface[MAX_BUF_SIZE]={'\0'};
956 char bridge_name[MAX_BUF_SIZE]={'\0'};
957 INT len=0;
958
959 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
960 //Not intitializing macfilter for Turris-Omnia Platform for now
961 //macfilter_init();
962
963 system("/usr/sbin/iw reg set US");
964 system("systemctl start hostapd.service");
965 sleep(2);//sleep to wait for hostapd to start
966
967 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
968
969 return RETURN_OK;
970}
971
972/* wifi_reset() function */
973/**
974* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
975* Implementation specifics may dictate what is actualy reset since
976* different hardware implementations may have different requirements.
977* Parameters : None
978*
979* @return The status of the operation.
980* @retval RETURN_OK if successful.
981* @retval RETURN_ERR if any error is detected
982*
983* @execution Synchronous.
984* @sideeffect None.
985*
986* @note This function must not suspend and must not invoke any blocking system
987* calls. It should probably just send a message to a driver event handler task.
988*
989*/
990INT wifi_reset()
991{
992 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +0800993 system("systemctl stop hostapd.service");
994 sleep(2);
995 system("systemctl start hostapd.service");
996 sleep(5);
developer06a01d92022-09-07 16:32:39 +0800997 return RETURN_OK;
998}
999
1000/* wifi_down() function */
1001/**
1002* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1003* Implementation specifics may dictate some functionality since
1004* different hardware implementations may have different requirements.
1005*
1006* @param None
1007*
1008* @return The status of the operation
1009* @retval RETURN_OK if successful
1010* @retval RETURN_ERR if any error is detected
1011*
1012* @execution Synchronous
1013* @sideeffect None
1014*
1015* @note This function must not suspend and must not invoke any blocking system
1016* calls. It should probably just send a message to a driver event handler task.
1017*
1018*/
1019INT wifi_down()
1020{
1021 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001022 system("systemctl stop hostapd.service");
1023 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001024 return RETURN_OK;
1025}
1026
1027
1028/* wifi_createInitialConfigFiles() function */
1029/**
1030* @description This function creates wifi configuration files. The format
1031* and content of these files are implementation dependent. This function call is
1032* used to trigger this task if necessary. Some implementations may not need this
1033* function. If an implementation does not need to create config files the function call can
1034* do nothing and return RETURN_OK.
1035*
1036* @param None
1037*
1038* @return The status of the operation
1039* @retval RETURN_OK if successful
1040* @retval RETURN_ERR if any error is detected
1041*
1042* @execution Synchronous
1043* @sideeffect None
1044*
1045* @note This function must not suspend and must not invoke any blocking system
1046* calls. It should probably just send a message to a driver event handler task.
1047*
1048*/
1049INT wifi_createInitialConfigFiles()
1050{
1051 //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)
1052 return RETURN_OK;
1053}
1054
1055// outputs the country code to a max 64 character string
1056INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1057{
developer7543b3b2022-09-13 13:47:17 +08001058 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1059 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001060 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001061
1062 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1063 _syscmd(cmd, buf, sizeof(buf));
1064 if(strlen(buf) > 0)
1065 snprintf(output_string, 64, "%s", buf);
1066 else
1067 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001068
1069 return RETURN_OK;
1070}
1071
1072INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1073{
1074 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001075 char str[MAX_BUF_SIZE]={'\0'};
1076 char cmd[MAX_CMD_SIZE]={'\0'};
1077 struct params params;
1078 char config_file[MAX_BUF_SIZE] = {0};
1079
1080 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1081 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1082 return RETURN_ERR;
1083
1084 params.name = "country_code";
1085 params.value = CountryCode;
1086 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1087 int ret = wifi_hostapdWrite(config_file, &params, 1);
1088 if (ret) {
1089 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1090 ,__func__, ret);
1091 }
1092
1093 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1094 if (ret) {
1095 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1096 ,__func__, ret);
1097 }
1098 wifi_reloadAp(radioIndex);
1099 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1100
developer06a01d92022-09-07 16:32:39 +08001101 return RETURN_OK;
1102}
1103
developera748dcf2022-09-13 15:56:48 +08001104INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1105{
1106 char channel_util_file[64] = {0};
1107 char cmd[128] = {0};
1108 char buf[128] = {0};
1109 char line[128] = {0};
1110 char *param = NULL, *value = NULL;
1111 int read = 0;
1112 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1113 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1114 size_t len = 0;
1115 FILE *f = NULL;
1116
1117 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1118
1119 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1120 _syscmd(cmd, buf, sizeof(buf));
1121 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1122
1123 memset(cmd, 0, sizeof(cmd));
1124 memset(buf, 0, sizeof(buf));
1125 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1126 if ((f = popen(cmd, "r")) == NULL) {
1127 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1128 return RETURN_ERR;
1129 }
1130
1131 read = getline(&line, &len, f);
1132 while (read != -1) {
1133 param = strtok(line, ":\t");
1134 value = strtok(NULL, " ");
1135 if(strstr(param, "frequency") != NULL) {
1136 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1137 }
1138 if(strstr(param, "noise") != NULL) {
1139 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1140 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1141 }
1142 if(strstr(param, "channel active time") != NULL) {
1143 ActiveTime = strtol(value, NULL, 10);
1144 }
1145 if(strstr(param, "channel busy time") != NULL) {
1146 BusyTime = strtol(value, NULL, 10);
1147 }
1148 if(strstr(param, "channel transmit time") != NULL) {
1149 TransmitTime = strtol(value, NULL, 10);
1150 }
1151 read = getline(&line, &len, f);
1152 }
1153 pclose(f);
1154
1155 // The file should store the last active, busy and transmit time
1156 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1157 f = fopen(channel_util_file, "r");
1158 if (f != NULL) {
1159 read = getline(&line, &len, f);
1160 preActiveTime = strtol(line, NULL, 10);
1161 read = getline(&line, &len, f);
1162 preBusyTime = strtol(line, NULL, 10);
1163 read = getline(&line, &len, f);
1164 preTransmitTime = strtol(line, NULL, 10);
1165 fclose(f);
1166 }
1167
1168 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1169 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1170
1171 f = fopen(channel_util_file, "w");
1172 if (f != NULL) {
1173 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1174 fclose(f);
1175 }
1176 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1177 return RETURN_OK;
1178}
1179
developer06a01d92022-09-07 16:32:39 +08001180/**********************************************************************************
1181 *
1182 * Wifi radio level function prototypes
1183 *
1184**********************************************************************************/
1185
1186//Get the total number of radios in this wifi subsystem
1187INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1188{
1189 if (NULL == output)
1190 return RETURN_ERR;
1191 *output = 2;
1192
1193 return RETURN_OK;
1194}
1195
1196//Get the total number of SSID entries in this wifi subsystem
1197INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1198{
1199 if (NULL == output)
1200 return RETURN_ERR;
1201 *output = MAX_APS;
1202
1203 return RETURN_OK;
1204}
1205
1206//Get the Radio enable config parameter
1207INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1208{
1209 char interface_path[MAX_CMD_SIZE] = {0};
1210 FILE *fp = NULL;
1211
1212 if (NULL == output_bool)
1213 return RETURN_ERR;
1214
1215 *output_bool = FALSE;
1216 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1217 return RETURN_ERR;
1218
1219 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1220 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001221 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001222 {
developercf48e482022-09-13 14:49:50 +08001223 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001224 }
1225 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001226 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1227 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1228 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001229
developercf48e482022-09-13 14:49:50 +08001230 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1231 *output_bool = TRUE;
1232 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001233 return RETURN_OK;
1234}
1235
1236INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1237{
1238 char cmd[MAX_CMD_SIZE] = {0};
1239 char buf[MAX_CMD_SIZE] = {0};
1240 int apIndex, ret;
1241 FILE *fp = NULL;
1242
1243 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1244 if(enable==FALSE)
1245 {
1246 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1247 {
1248 //Detaching %s%d from hostapd daemon
1249 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1250 _syscmd(cmd, buf, sizeof(buf));
1251 if(strncmp(buf, "OK", 2))
1252 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1253 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1254 _syscmd(cmd, buf, sizeof(buf));
1255 }
developer456aa3e2022-09-13 14:27:36 +08001256 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001257 _syscmd(cmd, buf, sizeof(buf));
1258 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001259 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001260 }
1261 else
1262 {
developer456aa3e2022-09-13 14:27:36 +08001263 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001264 _syscmd(cmd, buf, sizeof(buf));
1265 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001266 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001267 sleep(1);
1268 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1269 {
1270 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1271 fp = fopen(cmd, "r");
1272 if(!fp)
1273 {
1274 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1275 _syscmd(cmd, buf, sizeof(buf));
1276 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1277 _syscmd(cmd, buf, sizeof(buf));
1278 }
1279 if(fp)
1280 fclose(fp);
1281 }
1282 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1283 {
1284 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1285 ret = _syscmd(cmd, buf, sizeof(buf));
1286 if ( ret == RETURN_ERR)
1287 {
1288 fprintf(stderr, "VAP interface creation failed\n");
1289 continue;
1290 }
1291 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1292 _syscmd(cmd, buf, sizeof(buf));
1293 if(*buf == '1')
1294 {
1295 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1296 radioIndex, apIndex);
1297 _syscmd(cmd, buf, sizeof(buf));
1298 if(strncmp(buf, "OK", 2))
1299 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1300 }
1301 }
1302 }
1303
1304 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1305 return RETURN_OK;
1306}
1307
1308//Get the Radio enable status
1309INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1310{
1311 if (NULL == output_bool)
1312 return RETURN_ERR;
1313
1314 return wifi_getRadioEnable(radioIndex, output_bool);
1315}
1316
1317//Get the Radio Interface name from platform, eg "wlan0"
1318INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1319{
1320 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1321 return RETURN_ERR;
1322 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1323
1324 return RETURN_OK;
1325}
1326
1327//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1328//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.
1329INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1330{
developerbcc556a2022-09-22 20:02:45 +08001331 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1332 // For max bit rate, we should always choose the best MCS
1333 char mode[64] = {0};
1334 char channel_bandwidth_str[16] = {0};
1335 char *tmp = NULL;
1336 UINT mode_map = 0;
1337 UINT num_subcarrier = 0;
1338 UINT code_bits = 0;
1339 float code_rate = 0; // use max code rate
1340 int NSS = 0;
1341 UINT Symbol_duration = 0;
1342 UINT GI_duration = 0;
1343 wifi_band band = band_invalid;
1344 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1345 BOOL enable = FALSE;
1346 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001347
1348 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1349 if (NULL == output_string)
1350 return RETURN_ERR;
1351
developerbcc556a2022-09-22 20:02:45 +08001352 wifi_getRadioEnable(radioIndex, &enable);
1353 if (enable == FALSE) {
1354 snprintf(output_string, 64, "0 Mb/s");
1355 return RETURN_OK;
1356 }
1357
1358 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1359 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1360 return RETURN_ERR;
1361 }
1362
1363 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1364 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1365 return RETURN_ERR;
1366 }
1367
1368 if (gi == wifi_guard_interval_3200)
1369 GI_duration = 32;
1370 else if (gi == wifi_guard_interval_1600)
1371 GI_duration = 16;
1372 else if (gi == wifi_guard_interval_800)
1373 GI_duration = 8;
1374 else // auto, 400
1375 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001376
developerbcc556a2022-09-22 20:02:45 +08001377 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1378 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1379 return RETURN_ERR;
1380 }
1381
1382 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1383 strcpy(channel_bandwidth_str, "160");
1384
1385 if (mode_map & WIFI_MODE_AX) {
1386 if (strstr(channel_bandwidth_str, "160") != NULL)
1387 num_subcarrier = 1960;
1388 else if (strstr(channel_bandwidth_str, "80") != NULL)
1389 num_subcarrier = 980;
1390 else if (strstr(channel_bandwidth_str, "40") != NULL)
1391 num_subcarrier = 468;
1392 else if (strstr(channel_bandwidth_str, "20") != NULL)
1393 num_subcarrier = 234;
1394 code_bits = 10;
1395 code_rate = (float)5/6;
1396 Symbol_duration = 128;
1397 } else if (mode_map & WIFI_MODE_AC) {
1398 if (strstr(channel_bandwidth_str, "160") != NULL)
1399 num_subcarrier = 468;
1400 else if (strstr(channel_bandwidth_str, "80") != NULL)
1401 num_subcarrier = 234;
1402 else if (strstr(channel_bandwidth_str, "40") != NULL)
1403 num_subcarrier = 108;
1404 else if (strstr(channel_bandwidth_str, "20") != NULL)
1405 num_subcarrier = 52;
1406 code_bits = 8;
1407 code_rate = (float)5/6;
1408 Symbol_duration = 32;
1409 } else if (mode_map & WIFI_MODE_N) {
1410 if (strstr(channel_bandwidth_str, "160") != NULL)
1411 num_subcarrier = 468;
1412 else if (strstr(channel_bandwidth_str, "80") != NULL)
1413 num_subcarrier = 234;
1414 else if (strstr(channel_bandwidth_str, "40") != NULL)
1415 num_subcarrier = 108;
1416 else if (strstr(channel_bandwidth_str, "20") != NULL)
1417 num_subcarrier = 52;
1418 code_bits = 6;
1419 code_rate = (float)3/4;
1420 Symbol_duration = 32;
1421 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1422 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1423 snprintf(output_string, 64, "65 Mb/s");
1424 return RETURN_OK;
1425 } else {
1426 snprintf(output_string, 64, "0 Mb/s");
1427 return RETURN_OK;
1428 }
developer06a01d92022-09-07 16:32:39 +08001429
developerbcc556a2022-09-22 20:02:45 +08001430 // Spatial streams
1431 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1432 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1433 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001434 }
developerbcc556a2022-09-22 20:02:45 +08001435
1436 // multiple 10 is to align duration unit (0.1 us)
1437 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1438 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1439
developer06a01d92022-09-07 16:32:39 +08001440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1441
1442 return RETURN_OK;
1443}
1444#if 0
1445INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1446{
1447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1448 char cmd[64];
1449 char buf[1024];
1450 int apIndex;
1451
1452 if (NULL == output_string)
1453 return RETURN_ERR;
1454
1455 apIndex=(radioIndex==0)?0:1;
1456
1457 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1458 _syscmd(cmd,buf, sizeof(buf));
1459
1460 snprintf(output_string, 64, "%s", buf);
1461 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1462 return RETURN_OK;
1463}
1464#endif
1465
1466
1467//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1468//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.
1469INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1470{
developer963da0c2022-09-13 15:58:27 +08001471 wifi_band band = band_invalid;
1472
developer06a01d92022-09-07 16:32:39 +08001473 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1474 if (NULL == output_string)
1475 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001476
1477 band = wifi_index_to_band(radioIndex);
1478
1479 memset(output_string, 0, 10);
1480 if (band == band_2_4)
1481 strcpy(output_string, "2.4GHz");
1482 else if (band == band_5)
1483 strcpy(output_string, "5GHz");
1484 else if (band == band_6)
1485 strcpy(output_string, "6GHz");
1486 else
1487 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1489
1490 return RETURN_OK;
1491#if 0
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
1498 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1499 if (NULL == output_string)
1500 return RETURN_ERR;
1501
1502
1503 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1504
1505 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1506 {
1507 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1508 return RETURN_ERR;
1509 }
1510 ch=strchr(buf,'\n');
1511 *ch='\0';
1512 ch=strchr(buf,'=');
1513 if(ch==NULL)
1514 return RETURN_ERR;
1515
1516
1517 ch++;
1518
1519 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1520 strcpy(buf,"0");
1521 if(strlen(ch) == 1)
1522 ch=strcat(buf,ch);
1523
1524
1525 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1526
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
1546
1547 ch2++;
1548
1549
1550 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1551
1552 memset(buf,'\0',sizeof(buf));
1553 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1554 {
1555 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1556 return RETURN_ERR;
1557 }
1558 if (strstr(buf,"2.4") != NULL )
1559 strcpy(output_string,"2.4GHz");
1560 else if(strstr(buf,"5.") != NULL )
1561 strcpy(output_string,"5GHz");
1562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1563
1564 return RETURN_OK;
1565#endif
1566}
1567
1568//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1569//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.
1570INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1571{
1572 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1573 if (NULL == output_string)
1574 return RETURN_ERR;
1575 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1577
1578 return RETURN_OK;
1579#if 0
1580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1581 char buf[MAX_BUF_SIZE]={'\0'};
1582 char str[MAX_BUF_SIZE]={'\0'};
1583 char cmd[MAX_CMD_SIZE]={'\0'};
1584 char *ch=NULL;
1585 char *ch2=NULL;
1586 char ch1[5]="0";
1587
1588 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1589
1590 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1591 {
1592 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1593 return RETURN_ERR;
1594 }
1595
1596 ch=strchr(buf,'\n');
1597 *ch='\0';
1598 ch=strchr(buf,'=');
1599 if(ch==NULL)
1600 return RETURN_ERR;
1601 ch++;
1602
1603 if(strlen(ch)==1)
1604 {
1605 strcat(ch1,ch);
1606
1607 }
1608 else
1609 {
1610 strcpy(ch1,ch);
1611 }
1612
1613
1614
1615 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1616 if(_syscmd(cmd,str,64) == RETURN_ERR)
1617 {
1618 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1619 return RETURN_ERR;
1620 }
1621
1622
1623 ch2=strchr(str,'\n');
1624 //replace \n with \0
1625 *ch2='\0';
1626 ch2=strchr(str,'=');
1627 if(ch2==NULL)
1628 {
1629 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1630 return RETURN_ERR;
1631 }
1632 else
1633 wifi_dbg_printf("%s",ch2+1);
1634 ch2++;
1635
1636
1637 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1638 memset(buf,'\0',sizeof(buf));
1639 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1640 {
1641 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1642 return RETURN_ERR;
1643 }
1644
1645
1646 if(strstr(buf,"2.4")!=NULL)
1647 {
1648 strcpy(output_string,"2.4GHz");
1649 }
1650 if(strstr(buf,"5.")!=NULL)
1651 {
1652 strcpy(output_string,"5GHz");
1653 }
1654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1655 return RETURN_OK;
1656#endif
1657}
1658
1659//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1660//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.
1661INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1662{
developer963da0c2022-09-13 15:58:27 +08001663 char cmd[128]={0};
1664 char buf[128]={0};
1665 char temp_output[128] = {0};
1666 wifi_band band;
1667
1668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001669 if (NULL == output_string)
1670 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001671
1672 band = wifi_index_to_band(radioIndex);
1673 if (band == band_2_4) {
1674 strcat(temp_output, "b,g,");
1675 } else if (band == band_5) {
1676 strcat(temp_output, "a,");
1677 }
1678
1679 // ht capabilities
1680 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);
1681 _syscmd(cmd, buf, sizeof(buf));
1682 if (strncmp(buf, "0x00", 4) != 0) {
1683 strcat(temp_output, "n,");
1684 }
developer06a01d92022-09-07 16:32:39 +08001685
developer963da0c2022-09-13 15:58:27 +08001686 // vht capabilities
1687 if (band == band_5) {
1688 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1689 _syscmd(cmd, buf, sizeof(buf));
1690 if (strncmp(buf, "0x00000000", 10) != 0) {
1691 strcat(temp_output, "ac,");
1692 }
1693 }
1694
1695 // he capabilities
1696 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);
1697 _syscmd(cmd, buf, sizeof(buf));
1698 if (strncmp (buf, "0x0000", 6) != 0) {
1699 strcat(temp_output, "ax,");
1700 }
1701
1702 // Remove the last comma
1703 if (strlen(temp_output) != 0)
1704 temp_output[strlen(temp_output)-1] = '\0';
1705 strncpy(output_string, temp_output, strlen(temp_output));
1706 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001707 return RETURN_OK;
1708}
1709
1710//Get the radio operating mode, and pure mode flag. eg: "ac"
1711//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.
1712INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1713{
1714 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1715 if (NULL == output_string)
1716 return RETURN_ERR;
1717
1718 if (radioIndex == 0) {
1719 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1720 *gOnly = FALSE;
1721 *nOnly = TRUE;
1722 *acOnly = FALSE;
1723 } else {
1724 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1725 *gOnly = FALSE;
1726 *nOnly = FALSE;
1727 *acOnly = FALSE;
1728 }
1729 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1730
1731 return RETURN_OK;
1732#if 0
1733 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1734 char buf[64] = {0};
1735 char config_file[MAX_BUF_SIZE] = {0};
1736
1737 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1738 return RETURN_ERR;
1739
1740 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1741 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1742
1743 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1744 if (strlen(buf) == 0)
1745 {
1746 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1747 return RETURN_ERR;
1748 }
1749 if(strcmp(buf,"g")==0)
1750 {
1751 wifi_dbg_printf("\nG\n");
1752 *gOnly=TRUE;
1753 *nOnly=FALSE;
1754 *acOnly=FALSE;
1755 }
1756 else if(strcmp(buf,"n")==0)
1757 {
1758 wifi_dbg_printf("\nN\n");
1759 *gOnly=FALSE;
1760 *nOnly=TRUE;
1761 *acOnly=FALSE;
1762 }
1763 else if(strcmp(buf,"ac")==0)
1764 {
1765 wifi_dbg_printf("\nac\n");
1766 *gOnly=FALSE;
1767 *nOnly=FALSE;
1768 *acOnly=TRUE;
1769 }
1770 /* hostapd-5G.conf has "a" as hw_mode */
1771 else if(strcmp(buf,"a")==0)
1772 {
1773 wifi_dbg_printf("\na\n");
1774 *gOnly=FALSE;
1775 *nOnly=FALSE;
1776 *acOnly=FALSE;
1777 }
1778 else
1779 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1780
1781 //for a,n mode
1782 if(radioIndex == 1)
1783 {
1784 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1785 if(strcmp(buf,"1")==0)
1786 {
1787 strncpy(output_string, "n", 1);
1788 *nOnly=FALSE;
1789 }
1790 }
1791
1792 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1793 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1794 return RETURN_OK;
1795#endif
1796}
1797
developerdb744382022-09-13 15:34:54 +08001798INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1799{
1800 char cmd[128] = {0};
1801 char buf[64] = {0};
1802 char config_file[64] = {0};
1803 wifi_band band;
1804
1805 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1806 if(NULL == output_string || NULL == pureMode)
1807 return RETURN_ERR;
1808
1809 // grep all of the ieee80211 protocol config set to 1
1810 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1811 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1812 _syscmd(cmd, buf, sizeof(buf));
1813
1814 band = wifi_index_to_band(radioIndex);
1815 // puremode is a bit map
1816 *pureMode = 0;
1817 if (band == band_2_4) {
1818 strcat(output_string, "b,g");
1819 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1820 if (strstr(buf, "n") != NULL) {
1821 strcat(output_string, ",n");
1822 *pureMode |= WIFI_MODE_N;
1823 }
1824 if (strstr(buf, "ax") != NULL) {
1825 strcat(output_string, ",ax");
1826 *pureMode |= WIFI_MODE_AX;
1827 }
1828 } else if (band == band_5) {
1829 strcat(output_string, "a");
1830 *pureMode |= WIFI_MODE_A;
1831 if (strstr(buf, "n") != NULL) {
1832 strcat(output_string, ",n");
1833 *pureMode |= WIFI_MODE_N;
1834 }
1835 if (strstr(buf, "ac") != NULL) {
1836 strcat(output_string, ",ac");
1837 *pureMode |= WIFI_MODE_AC;
1838 }
1839 if (strstr(buf, "ax") != NULL) {
1840 strcat(output_string, ",ax");
1841 *pureMode |= WIFI_MODE_AX;
1842 }
1843 } else if (band == band_6) {
1844 if (strstr(buf, "ax") != NULL) {
1845 strcat(output_string, "ax");
1846 *pureMode |= WIFI_MODE_AX;
1847 }
1848 }
1849
1850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1851 return RETURN_OK;
1852}
1853
1854// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001855INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1856{
1857 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1858 if (strcmp (channelMode,"11A") == 0)
1859 {
1860 writeBandWidth(radioIndex,"20MHz");
1861 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1862 printf("\nChannel Mode is 802.11a (5GHz)\n");
1863 }
1864 else if (strcmp (channelMode,"11NAHT20") == 0)
1865 {
1866 writeBandWidth(radioIndex,"20MHz");
1867 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1868 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1869 }
1870 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1871 {
1872 writeBandWidth(radioIndex,"40MHz");
1873 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1874 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1875 }
1876 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1877 {
1878 writeBandWidth(radioIndex,"40MHz");
1879 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1880 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1881 }
1882 else if (strcmp (channelMode,"11ACVHT20") == 0)
1883 {
1884 writeBandWidth(radioIndex,"20MHz");
1885 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1886 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1887 }
1888 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1889 {
1890 writeBandWidth(radioIndex,"40MHz");
1891 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1892 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1893 }
1894 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1895 {
1896 writeBandWidth(radioIndex,"40MHz");
1897 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1898 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1899 }
1900 else if (strcmp (channelMode,"11ACVHT80") == 0)
1901 {
1902 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1903 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1904 }
1905 else if (strcmp (channelMode,"11ACVHT160") == 0)
1906 {
1907 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1908 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1909 }
1910 else if (strcmp (channelMode,"11B") == 0)
1911 {
1912 writeBandWidth(radioIndex,"20MHz");
1913 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1914 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1915 }
1916 else if (strcmp (channelMode,"11G") == 0)
1917 {
1918 writeBandWidth(radioIndex,"20MHz");
1919 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1920 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1921 }
1922 else if (strcmp (channelMode,"11NGHT20") == 0)
1923 {
1924 writeBandWidth(radioIndex,"20MHz");
1925 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1926 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1927 }
1928 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1929 {
1930 writeBandWidth(radioIndex,"40MHz");
1931 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1932 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1933 }
1934 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1935 {
1936 writeBandWidth(radioIndex,"40MHz");
1937 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1938 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1939 }
1940 else
1941 {
1942 return RETURN_ERR;
1943 }
1944 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1945
1946 return RETURN_OK;
1947}
1948
developerdb744382022-09-13 15:34:54 +08001949// Set the radio operating mode, and pure mode flag.
1950INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1951{
1952 int num_hostapd_support_mode = 3; // n, ac, ax
1953 struct params list[num_hostapd_support_mode];
1954 char config_file[64] = {0};
1955 char bandwidth[16] = {0};
1956 int mode_check_bit = 1 << 3; // n mode
1957 wifi_ieee80211_Mode mode = (wifi_ieee80211_Mode)pureMode;
1958
1959 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1960 // Set radio mode
1961 list[0].name = "ieee80211n";
1962 list[1].name = "ieee80211ac";
1963 list[2].name = "ieee80211ax";
1964 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1965
1966 // check the bit map from n to ax, and set hostapd config
1967 if (mode & WIFI_MODE_N)
1968 list[0].value = "1";
1969 else
1970 list[0].value = "0";
1971 if (mode & WIFI_MODE_AC)
1972 list[1].value = "1";
1973 else
1974 list[1].value = "0";
1975 if (mode & WIFI_MODE_AX)
1976 list[2].value = "1";
1977 else
1978 list[2].value = "0";
1979 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1980
1981 if (channelMode == NULL || strlen(channelMode) == 0)
1982 return RETURN_OK;
1983 // Set bandwidth
1984 if (strstr(channelMode, "40") != NULL)
1985 strcpy(bandwidth, "40MHz");
1986 else if (strstr(channelMode, "80") != NULL)
1987 strcpy(bandwidth, "80MHz");
1988 else if (strstr(channelMode, "160") != NULL)
1989 strcpy(bandwidth, "160MHz");
1990 else // 11A, 11B, 11G....
1991 strcpy(bandwidth, "20MHz");
1992
1993 writeBandWidth(radioIndex, bandwidth);
1994 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
1995
1996 wifi_reloadAp(radioIndex);
1997 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1998
1999 return RETURN_OK;
2000}
2001
developer06a01d92022-09-07 16:32:39 +08002002//Get the list of supported channel. eg: "1-11"
2003//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.
2004INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2005{
developer6318ed52022-09-13 15:17:58 +08002006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002007 if (NULL == output_string)
2008 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002009 char cmd[256] = {0};
2010 char buf[128] = {0};
2011 BOOL dfs_enable = false;
2012 // Parse possible channel number and separate them with commas.
2013 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2014 if (dfs_enable)
2015 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
2016 else
2017 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);
2018
2019 _syscmd(cmd,buf,sizeof(buf));
2020 strncpy(output_string, buf, sizeof(buf));
2021
2022 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2023 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002024#if 0
2025 char IFName[50] ={0};
2026 char buf[MAX_BUF_SIZE] = {0};
2027 char cmd[MAX_CMD_SIZE] = {0};
2028 int count = 0;
2029 if (NULL == output_string)
2030 return RETURN_ERR;
2031
2032 //snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2033 if(radioIndex == 0)
2034 {
2035 GetInterfaceName(IFName,"/nvram/hostapd0.conf");
2036 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'");
2037 }
2038 else if(radioIndex == 1)
2039 {
2040 GetInterfaceName(IFName,"/nvram/hostapd1.conf");
2041 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'");
2042 }
2043 _syscmd(cmd, buf, sizeof(buf));
2044 if(strlen(buf) > 0)
2045 strcpy(output_string,buf);
2046 else
2047 strcpy(output_string,"0");
2048#endif
2049 return RETURN_OK;
2050}
2051
2052//Get the list for used channel. eg: "1,6,9,11"
2053//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.
2054INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2055{
2056 if (NULL == output_string)
2057 return RETURN_ERR;
2058 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
2059#if 0
2060 char IFName[50] ={0};
2061 char buf[MAX_BUF_SIZE] = {0};
2062 char cmd[MAX_CMD_SIZE] = {0};
2063 if (NULL == output_string)
2064 return RETURN_ERR;
2065
2066 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2067 if(radioIndex == 0)
2068 {
2069 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
2070 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'");
2071 }
2072 else if(radioIndex == 1)
2073 {
2074 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
2075 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'");
2076 }
2077 _syscmd(cmd,buf, sizeof(buf));
2078 if(strlen(buf) > 0)
2079 strcpy(output_string,buf);
2080 else
2081 strcpy(output_string,"0");
2082#endif
2083 return RETURN_OK;
2084}
2085
2086//Get the running channel number
2087INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2088{
developerda1ed692022-09-13 13:59:20 +08002089#ifdef MTK_IMPL
2090 if(!wifi_getApChannel(radioIndex, output_ulong))
2091 return RETURN_OK;
2092 else
2093 return RETURN_ERR;
2094#else
developer06a01d92022-09-07 16:32:39 +08002095 char cmd[1024] = {0}, buf[5] = {0};
2096
2097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2098 if (NULL == output_ulong)
2099 return RETURN_ERR;
2100
2101 snprintf(cmd, sizeof(cmd),
2102 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2103 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2104 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2105 _syscmd(cmd, buf, sizeof(buf));
2106
2107 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2108 if (*output_ulong <= 0) {
2109 *output_ulong = 0;
2110 return RETURN_ERR;
2111 }
2112
2113 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2114 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002115#endif
developer06a01d92022-09-07 16:32:39 +08002116}
2117
2118
2119INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2120{
2121 char cmd[1024] = {0}, buf[5] = {0};
2122 char interface_name[50] = {0};
2123
2124 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2125 if (NULL == output_ulong)
2126 return RETURN_ERR;
2127
2128 wifi_getApName(apIndex,interface_name);
2129 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2130 _syscmd(cmd,buf,sizeof(buf));
2131 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2132 if (*output_ulong == 0) {
2133 return RETURN_ERR;
2134 }
2135
2136 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2137 return RETURN_OK;
2138}
2139
2140//Storing the previous channel value
2141INT wifi_storeprevchanval(INT radioIndex)
2142{
2143 char buf[256] = {0};
2144 char output[4]={'\0'};
2145 char config_file[MAX_BUF_SIZE] = {0};
2146 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2147 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2148 if(radioIndex == 0)
2149 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2150 else if(radioIndex == 1)
2151 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2152 system(buf);
2153 Radio_flag = FALSE;
2154 return RETURN_OK;
2155}
2156
2157//Set the running channel number
2158INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2159{
2160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2161 struct params params={'\0'};
2162 char str_channel[4]={'\0'};
2163 struct params list;
2164 char config_file[MAX_BUF_SIZE] = {0};
2165
2166 list.name = "channel";
2167
2168 if(Radio_flag == TRUE)
2169 wifi_storeprevchanval(radioIndex); //for autochannel
2170
2171 if(radioIndex == 0)
2172 {
2173 switch(channel)
2174 {
2175 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
2176 sprintf(str_channel,"%ld", channel);
2177 list.value = str_channel;
2178 break;
2179 default:
2180 return RETURN_ERR;
2181 }
2182 }
2183 else if(radioIndex == 1)
2184 {
2185 switch(channel)
2186 {
2187 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:
2188 sprintf(str_channel,"%ld", channel);
2189 list.value = str_channel;
2190 break;
2191 default:
2192 return RETURN_ERR;
2193 }
2194 }
2195
2196 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS;i++)
2197 {
2198 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2199 wifi_hostapdWrite(config_file,&list,1);
2200 }
2201
2202 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2203 return RETURN_OK;
2204 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2205 }
2206
2207INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2208{
2209 struct params list;
2210 char str_idx[16];
2211 char config_file[MAX_BUF_SIZE];
2212
2213 list.name = "vht_oper_centr_freq_seg0_idx";
2214 snprintf(str_idx, sizeof(str_idx), "%d", channel);
2215 list.value = str_idx;
2216
2217 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2218 {
2219 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2220 wifi_hostapdWrite(config_file, &list, 1);
2221 }
2222
2223 return RETURN_OK;
2224}
2225
2226//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2227//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2228INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2229{
2230 //Set to wifi config only. Wait for wifi reset to apply.
2231 char buf[256] = {0};
2232 char str_channel[256] = {0};
2233 int count = 0;
2234 ULONG Value = 0;
2235 FILE *fp = NULL;
2236 if(enable == TRUE)
2237 {
2238 if(radioIndex == 0)
2239 {
2240 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
2241 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
2242 }
2243 else if(radioIndex == 1)
2244 {
2245 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
2246 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
2247 }
2248 if(fp == NULL) //first time boot-up
2249 {
2250 if(radioIndex == 0)
2251 Value = 6;
2252 else if(radioIndex == 1)
2253 Value = 36;
2254 }
2255 else
2256 {
2257 if(fgets(buf,sizeof(buf),fp) != NULL)
2258 {
2259 for(count = 0;buf[count]!='\n';count++)
2260 str_channel[count] = buf[count];
2261 str_channel[count] = '\0';
2262 Value = atol(str_channel);
2263 printf("%sValue is %ld \n",__FUNCTION__,Value);
2264 pclose(fp);
2265 }
2266 }
2267 Radio_flag = FALSE;//for storing previous channel value
2268 wifi_setRadioChannel(radioIndex,Value);
2269 return RETURN_OK;
2270 }
2271 return RETURN_ERR;
2272}
2273
developer0b246d12022-09-30 15:24:20 +08002274INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2275{
2276 if (output_bool == NULL)
2277 return RETURN_ERR;
2278
2279 *output_bool = TRUE;
2280
2281 return RETURN_OK;
2282}
2283
developer06a01d92022-09-07 16:32:39 +08002284INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2285{
2286 if (NULL == output_bool)
2287 return RETURN_ERR;
2288 *output_bool=FALSE;
2289 return RETURN_OK;
2290}
2291
2292INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2293{
2294 if (NULL == output_bool)
2295 return RETURN_ERR;
2296 *output_bool=FALSE;
2297 return RETURN_OK;
2298}
2299
2300INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2301{
2302 //Set to wifi config only. Wait for wifi reset to apply.
2303 return RETURN_OK;
2304}
2305
2306INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2307{
2308 return RETURN_OK;
2309}
2310
2311INT wifi_factoryResetAP(int apIndex)
2312{
2313 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2314 //factory reset is not done for now on Turris
2315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2316 return RETURN_OK;
2317}
2318
2319//To set Band Steering AP group
2320//To-do
2321INT wifi_setBandSteeringApGroup(char *ApGroup)
2322{
2323 return RETURN_OK;
2324}
2325
developer1e5aa162022-09-13 16:06:24 +08002326INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2327{
2328 char config_file[128] = {'\0'};
2329 char buf[128] = {'\0'};
2330
2331 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2332 if (dtimInterval == NULL)
2333 return RETURN_ERR;
2334
2335 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2336 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2337
2338 if (strlen(buf) == 0) {
2339 *dtimInterval = 2;
2340 } else {
2341 *dtimInterval = strtoul(buf, NULL, 10);
2342 }
2343
2344 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2345 return RETURN_OK;
2346}
2347
developer06a01d92022-09-07 16:32:39 +08002348INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2349{
developer5f222492022-09-13 15:21:52 +08002350 struct params params={0};
2351 char config_file[MAX_BUF_SIZE] = {'\0'};
2352 char buf[MAX_BUF_SIZE] = {'\0'};
2353
2354 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2355 if (dtimInterval < 1 || dtimInterval > 255) {
2356 return RETURN_ERR;
2357 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2358 }
2359
2360 params.name = "dtim_period";
2361 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2362 params.value = buf;
2363
2364 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2365 wifi_hostapdWrite(config_file, &params, 1);
2366 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2367
2368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2369 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002370}
2371
2372//Check if the driver support the Dfs
2373INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2374{
2375 if (NULL == output_bool)
2376 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002377 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002378 return RETURN_OK;
2379}
2380
2381//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.
2382//The value of this parameter is a comma seperated list of channel number
2383INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2384{
2385 if (NULL == output_pool)
2386 return RETURN_ERR;
2387 if (radioIndex==1)
2388 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2389 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2390
2391 return RETURN_OK;
2392}
2393
2394INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2395{
2396 //Set to wifi config. And apply instantly.
2397 return RETURN_OK;
2398}
2399
2400INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2401{
2402 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2403 return RETURN_ERR;
2404 *output_interval_seconds=1800;
2405 *output_dwell_milliseconds=40;
2406
2407 return RETURN_OK;
2408}
2409
2410INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2411{
2412 //Set to wifi config. And apply instantly.
2413 return RETURN_OK;
2414}
2415
2416//Get the Dfs enable status
2417INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2418{
developer9964b5b2022-09-13 15:59:34 +08002419 char buf[16] = {0};
2420 FILE *f = NULL;
2421 wifi_band band;
2422
2423 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2424
2425 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002426 if (NULL == output_bool)
2427 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002428
2429 band = wifi_index_to_band(radioIndex);
2430 if (band != band_5)
2431 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002432
developer9964b5b2022-09-13 15:59:34 +08002433 f = fopen(DFS_ENABLE_FILE, "r");
2434 if (f != NULL) {
2435 fgets(buf, 2, f);
2436 if (strncmp(buf, "0", 0) == 0)
2437 *output_bool = FALSE;
2438 fclose(f);
2439 }
2440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002441 return RETURN_OK;
2442}
2443
2444//Set the Dfs enable status
2445INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2446{
developer9964b5b2022-09-13 15:59:34 +08002447 char buf[128] = {0};
2448 char config_file[128] = {0};
2449 FILE *f = NULL;
2450 struct params params={0};
2451 wifi_band band;
2452
2453 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2454
2455 band = wifi_index_to_band(radioIndex);
2456 if (band != band_5)
2457 return RETURN_OK;
2458
2459 f = fopen(DFS_ENABLE_FILE, "w");
2460 if (f == NULL)
2461 return RETURN_ERR;
2462 fprintf(f, "%d", enable);
2463 fclose(f);
2464
2465 params.name = "acs_exclude_dfs";
2466 sprintf(buf, "%d", enable?"1":"0");
2467 params.value = buf;
2468 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2469 wifi_hostapdWrite(config_file, &params, 1);
2470 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2471
2472 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2473
2474 wifi_reloadAp(radioIndex);
2475
2476 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002477}
2478
2479//Check if the driver support the AutoChannelRefreshPeriod
2480INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2481{
2482 if (NULL == output_bool)
2483 return RETURN_ERR;
2484 *output_bool=FALSE; //not support
2485
2486 return RETURN_OK;
2487}
2488
2489//Get the ACS refresh period in seconds
2490INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2491{
2492 if (NULL == output_ulong)
2493 return RETURN_ERR;
2494 *output_ulong=300;
2495
2496 return RETURN_OK;
2497}
2498
2499//Set the ACS refresh period in seconds
2500INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2501{
2502 return RETURN_ERR;
2503}
2504
2505//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2506//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.
2507INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2508{
developer70490032022-09-13 15:45:20 +08002509 char cmd[128] = {0}, buf[64] = {0};
2510 char interface_name[64] = {0};
2511 int ret = 0, len=0;
2512 BOOL radio_enable = FALSE;
2513
2514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2515
developer06a01d92022-09-07 16:32:39 +08002516 if (NULL == output_string)
2517 return RETURN_ERR;
2518
developer70490032022-09-13 15:45:20 +08002519 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2520 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002521
developer70490032022-09-13 15:45:20 +08002522 if (radio_enable != TRUE)
2523 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002524
developer70490032022-09-13 15:45:20 +08002525 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002526 ret = _syscmd(cmd, buf, sizeof(buf));
2527 len = strlen(buf);
2528 if((ret != 0) || (len == 0))
2529 {
2530 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2531 return RETURN_ERR;
2532 }
2533
2534 buf[len-1] = '\0';
2535 snprintf(output_string, 64, "%sMHz", buf);
2536 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2537
2538#if 0
2539 //TODO: revisit below implementation
2540 char output_buf[8]={0};
2541 char bw_value[10];
2542 char config_file[MAX_BUF_SIZE] = {0};
2543
2544 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2545 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2546 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2547 readBandWidth(radioIndex,bw_value);
2548
2549 if(strstr (output_buf,"0") != NULL )
2550 {
2551 strcpy(output_string,bw_value);
2552 }
2553 else if (strstr (output_buf,"1") != NULL)
2554 {
2555 strcpy(output_string,"80MHz");
2556 }
2557 else if (strstr (output_buf,"2") != NULL)
2558 {
2559 strcpy(output_string,"160MHz");
2560 }
2561 else if (strstr (output_buf,"3") != NULL)
2562 {
2563 strcpy(output_string,"80+80");
2564 }
2565 else
2566 {
2567 strcpy(output_string,"Auto");
2568 }
2569 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2570#endif
2571
2572 return RETURN_OK;
2573}
2574
2575//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002576INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002577{
developerf7a466e2022-09-29 11:55:56 +08002578 char config_file[128];
2579 char set_value[16];
2580 struct params params[2];
2581 int max_radio_num = 0;
2582
developer06a01d92022-09-07 16:32:39 +08002583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002584
developerf7a466e2022-09-29 11:55:56 +08002585 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002586 return RETURN_ERR;
2587
developerf7a466e2022-09-29 11:55:56 +08002588 if(strstr(bandwidth,"80+80") != NULL)
2589 strcpy(set_value, "3");
2590 else if(strstr(bandwidth,"160") != NULL)
2591 strcpy(set_value, "2");
2592 else if(strstr(bandwidth,"80") != NULL)
2593 strcpy(set_value, "1");
2594 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2595 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002596 else
2597 {
developerf7a466e2022-09-29 11:55:56 +08002598 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002599 return RETURN_ERR;
2600 }
2601
developerf7a466e2022-09-29 11:55:56 +08002602 params[0].name = "vht_oper_chwidth";
2603 params[0].value = set_value;
2604 params[1].name = "he_oper_chwidth";
2605 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002606
developerf7a466e2022-09-29 11:55:56 +08002607 wifi_getMaxRadioNumber(&max_radio_num);
2608 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002609 {
developerf7a466e2022-09-29 11:55:56 +08002610 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2611 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002612 }
2613
2614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2615 return RETURN_OK;
2616}
2617
2618//Getting current radio extension channel
2619INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2620{
2621 CHAR buf[150] = {0};
2622 CHAR cmd[150] = {0};
2623 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2624 _syscmd(cmd, buf, sizeof(buf));
2625 if(NULL != strstr(buf,"HT40+"))
2626 strcpy(Value,"AboveControlChannel");
2627 else if(NULL != strstr(buf,"HT40-"))
2628 strcpy(Value,"BelowControlChannel");
2629 return RETURN_OK;
2630}
2631
2632//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2633//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.
2634INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2635{
2636 if (NULL == output_string)
2637 return RETURN_ERR;
2638
2639 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2640#if 0
2641 CHAR Value[100] = {0};
2642 if (NULL == output_string)
2643 return RETURN_ERR;
2644 if(radioIndex == 0)
2645 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2646 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2647 {
2648 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2649 if(strcmp(Value,"40MHz") == 0)
2650 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2651 else
2652 strcpy(Value,"Auto");
2653 }
2654 strcpy(output_string,Value);
2655#endif
2656
2657 return RETURN_OK;
2658}
2659
2660//Set the extension channel.
2661INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2662{
2663 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2664 struct params params={'\0'};
2665 char config_file[MAX_BUF_SIZE] = {0};
2666 char ext_channel[127]={'\0'};
2667
2668 params.name = "ht_capab";
2669
2670 if(radioIndex == 0)
2671 {
2672 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002673 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002674 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002675 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002676 else
developer3cc0f2e2022-09-15 18:25:39 +08002677 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002678 }
2679 else if(radioIndex == 1)
2680 {
2681 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002682 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002683 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002684 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002685 else
developer3cc0f2e2022-09-15 18:25:39 +08002686 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002687 }
2688
2689 params.value = ext_channel;
2690 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2691 {
2692 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2693 wifi_hostapdWrite(config_file, &params, 1);
2694 }
2695
2696 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2697 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2698 return RETURN_OK;
2699}
2700
2701//Get the guard interval value. eg "400nsec" or "800nsec"
2702//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.
2703INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2704{
developer454b9462022-09-13 15:29:16 +08002705 wifi_guard_interval_t GI;
2706
2707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2708
2709 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002710 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002711
2712 if (GI == wifi_guard_interval_400)
2713 strcpy(output_string, "400nsec");
2714 else if (GI == wifi_guard_interval_800)
2715 strcpy(output_string, "800nsec");
2716 else if (GI == wifi_guard_interval_1600)
2717 strcpy(output_string, "1600nsec");
2718 else if (GI == wifi_guard_interval_3200)
2719 strcpy(output_string, "3200nsec");
2720 else
2721 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002722
developer454b9462022-09-13 15:29:16 +08002723 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002724 return RETURN_OK;
2725}
2726
2727//Set the guard interval value.
2728INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2729{
developer454b9462022-09-13 15:29:16 +08002730 wifi_guard_interval_t GI;
2731 int ret = 0;
2732
2733 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2734
2735 if (strcmp(string, "400nsec") == 0)
2736 GI = wifi_guard_interval_400;
2737 else if (strcmp(string , "800nsec") == 0 || strcmp(string, "auto") == 0)
2738 GI = wifi_guard_interval_800;
2739 else if (strcmp(string , "1600nsec") == 0)
2740 GI = wifi_guard_interval_1600;
2741 else if (strcmp(string , "3200nsec") == 0)
2742 GI = wifi_guard_interval_3200;
2743
2744 ret = wifi_setGuardInterval(radioIndex, GI);
2745
2746 if (ret == RETURN_ERR) {
2747 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2748 return RETURN_ERR;
2749 }
2750
2751 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2752 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002753}
2754
2755//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2756INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2757{
developerf49437e2022-09-29 19:58:21 +08002758 char buf[32]={0};
2759 char mcs_file[64] = {0};
2760 char cmd[64] = {0};
2761 int mode_bitmap = 0;
2762
2763 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2764 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002765 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002766 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2767
2768 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2769 _syscmd(cmd, buf, sizeof(buf));
2770 if (strlen(buf) > 0)
2771 *output_int = strtol(buf, NULL, 10);
2772 else {
2773 // output the max MCS for the current radio mode
2774 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2775 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2776 return RETURN_ERR;
2777 }
2778 if (mode_bitmap & WIFI_MODE_AX) {
2779 *output_int = 11;
2780 } else if (mode_bitmap & WIFI_MODE_AC) {
2781 *output_int = 9;
2782 } else if (mode_bitmap & WIFI_MODE_N) {
2783 *output_int = 7;
2784 }
2785 }
2786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002787
2788 return RETURN_OK;
2789}
2790
2791//Set the Modulation Coding Scheme index
2792INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2793{
developerf49437e2022-09-29 19:58:21 +08002794 // Only HE mode can specify MCS capability. We don't support MCS in HT mode, because that would be ambiguous (MCS code 8~11 refer to 2 NSS in HT but 1 NSS in HE adn VHT).
2795 char config_file[64] = {0};
2796 char set_value[16] = {0};
2797 char mcs_file[32] = {0};
2798 wifi_band band = band_invalid;
2799 struct params set_config = {0};
2800 FILE *f = NULL;
2801
2802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2803
2804 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2805
2806 if (MCS > 11 || MCS < 0) {
2807 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2808 return RETURN_ERR;
2809 }
2810
2811 if (MCS <= 7)
2812 strcpy(set_value, "0");
2813 else if (MCS <= 9)
2814 strcpy(set_value, "1");
2815 else
2816 strcpy(set_value, "2");
2817
2818 set_config.name = "he_basic_mcs_nss_set";
2819 set_config.value = set_value;
2820
2821 wifi_hostapdWrite(config_file, &set_config, 1);
2822 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2823
2824 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2825 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2826 f = fopen(mcs_file, "w");
2827 if (f == NULL) {
2828 fprintf(stderr, "%s: fopen failed\n", __func__);
2829 return RETURN_ERR;
2830 }
2831 fprintf(f, "%d", MCS);
2832 fclose(f);
2833
2834 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2835 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002836}
2837
2838//Get supported Transmit Power list, eg : "0,25,50,75,100"
2839//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.
2840INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2841{
2842 if (NULL == output_list)
2843 return RETURN_ERR;
2844 snprintf(output_list, 64,"0,25,50,75,100");
2845 return RETURN_OK;
2846}
2847
developera5005b62022-09-13 15:43:35 +08002848//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002849//The transmite power level is in units of full power for this radio.
2850INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2851{
2852 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002853 char buf[16]={0};
2854 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002855
developera5005b62022-09-13 15:43:35 +08002856 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002857 return RETURN_ERR;
2858
developera5005b62022-09-13 15:43:35 +08002859 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 +08002860 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002861
developera5005b62022-09-13 15:43:35 +08002862 *output_ulong = strtol(buf, NULL, 10);
2863
2864 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002865 return RETURN_OK;
2866}
2867
2868//Set Transmit Power
2869//The transmite power level is in units of full power for this radio.
2870INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2871{
developera5005b62022-09-13 15:43:35 +08002872 char *support;
developer06a01d92022-09-07 16:32:39 +08002873 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002874 char buf[128]={0};
2875 char txpower_str[64] = {0};
2876 int txpower = 0;
2877 int maximum_tx = 0;
2878
2879 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002880
developera5005b62022-09-13 15:43:35 +08002881 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 +08002882 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002883 maximum_tx = strtol(buf, NULL, 10);
2884
2885 // Get the Tx power supported list and check that is the input in the list
2886 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2887 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2888 support = strtok(buf, ",");
2889 while(true)
2890 {
2891 if(support == NULL) { // input not in the list
2892 wifi_dbg_printf("Input value is invalid.\n");
2893 return RETURN_ERR;
2894 }
2895 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2896 break;
2897 }
2898 support = strtok(NULL, ",");
2899 }
2900 txpower = TransmitPower*maximum_tx/100;
2901 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2902 _syscmd(cmd, buf, sizeof(buf));
2903 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002904
2905 return RETURN_OK;
2906}
2907
2908//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2909INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2910{
2911 if (NULL == Supported)
2912 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002913 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002914
2915 return RETURN_OK;
2916}
2917
2918//Get 80211h feature enable
2919INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2920{
developer3885fec2022-09-13 15:13:47 +08002921 char buf[64]={'\0'};
2922 char config_file[64] = {'\0'};
2923
2924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2925 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002926 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002927
2928 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2929 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002930
developer3885fec2022-09-13 15:13:47 +08002931 if (strncmp(buf, "1", 1) == 0)
2932 *enable = TRUE;
2933 else
2934 *enable = FALSE;
2935
2936 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002937 return RETURN_OK;
2938}
2939
2940//Set 80211h feature enable
2941INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2942{
developer3885fec2022-09-13 15:13:47 +08002943 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2944 struct params params={'\0'};
2945 char config_file[MAX_BUF_SIZE] = {0};
2946
2947 params.name = "ieee80211h";
2948
2949 if (enable) {
2950 params.value = "1";
2951 } else {
2952 params.value = "0";
2953 }
2954
2955 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2956 wifi_hostapdWrite(config_file, &params, 1);
2957
2958 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2959 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2960 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002961}
2962
2963//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.
2964INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2965{
2966 if (NULL == output)
2967 return RETURN_ERR;
2968 *output=100;
2969
2970 return RETURN_OK;
2971}
2972
2973//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.
2974INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2975{
2976 if (NULL == output)
2977 return RETURN_ERR;
2978 *output = -99;
2979
2980 return RETURN_OK;
2981}
2982
2983INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2984{
2985 return RETURN_ERR;
2986}
2987
2988
2989//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2990INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2991{
developer5f222492022-09-13 15:21:52 +08002992 char cmd[MAX_BUF_SIZE]={'\0'};
2993 char buf[MAX_CMD_SIZE]={'\0'};
2994
2995 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2996 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08002997 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002998
2999 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3000 _syscmd(cmd, buf, sizeof(buf));
3001 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003002
developer5f222492022-09-13 15:21:52 +08003003 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003004 return RETURN_OK;
3005}
3006
3007INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3008{
developer5f222492022-09-13 15:21:52 +08003009 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3010 struct params params={'\0'};
3011 char buf[MAX_BUF_SIZE] = {'\0'};
3012 char config_file[MAX_BUF_SIZE] = {'\0'};
3013
3014 params.name = "beacon_int";
3015 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3016 params.value = buf;
3017
3018 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3019 wifi_hostapdWrite(config_file, &params, 1);
3020
3021 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3022 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3023 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003024}
3025
3026//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.
3027INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3028{
developer06a01d92022-09-07 16:32:39 +08003029 //TODO: need to revisit below implementation
3030 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003031 char temp_output[128] = {0};
3032 char temp_TransmitRates[64] = {0};
3033 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003034
3035 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3036 if (NULL == output)
3037 return RETURN_ERR;
3038 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003039 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3040
3041 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3042 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3043 } else {
3044 temp = strtok(temp_TransmitRates," ");
3045 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003046 {
developere9d0abd2022-09-13 15:40:57 +08003047 // Convert 100 kbps to Mbps
3048 temp[strlen(temp)-1]=0;
3049 if((temp[0]=='5') && (temp[1]=='\0'))
3050 {
3051 temp="5.5";
3052 }
3053 strcat(temp_output,temp);
3054 temp = strtok(NULL," ");
3055 if(temp!=NULL)
3056 {
3057 strcat(temp_output,",");
3058 }
developer06a01d92022-09-07 16:32:39 +08003059 }
developere9d0abd2022-09-13 15:40:57 +08003060 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003061 }
developer06a01d92022-09-07 16:32:39 +08003062 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003063 return RETURN_OK;
3064}
3065
3066INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3067{
3068 char *temp;
3069 char temp1[128];
3070 char temp_output[128];
3071 char temp_TransmitRates[128];
3072 char set[128];
3073 char sub_set[128];
3074 int set_count=0,subset_count=0;
3075 int set_index=0,subset_index=0;
3076 char *token;
3077 int flag=0, i=0;
3078 struct params params={'\0'};
3079 char config_file[MAX_BUF_SIZE] = {0};
3080
3081 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3082 if(NULL == TransmitRates)
3083 return RETURN_ERR;
3084 strcpy(sub_set,TransmitRates);
3085
3086 //Allow only supported Data transmit rate to be set
3087 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3088 token = strtok(sub_set,",");
3089 while( token != NULL ) /* split the basic rate to be set, by comma */
3090 {
3091 sub_set[subset_count]=atoi(token);
3092 subset_count++;
3093 token=strtok(NULL,",");
3094 }
3095 token=strtok(set,",");
3096 while(token!=NULL) /* split the supported rate by comma */
3097 {
3098 set[set_count]=atoi(token);
3099 set_count++;
3100 token=strtok(NULL,",");
3101 }
3102 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3103 {
3104 for(set_index=0;set_index < set_count;set_index++)
3105 {
3106 flag=0;
3107 if(sub_set[subset_index]==set[set_index])
3108 break;
3109 else
3110 flag=1; /* No match found */
3111 }
3112 if(flag==1)
3113 return RETURN_ERR; //If value not found return Error
3114 }
3115 strcpy(temp_TransmitRates,TransmitRates);
3116
3117 for(i=0;i<strlen(temp_TransmitRates);i++)
3118 {
3119 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3120 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3121 {
3122 continue;
3123 }
3124 else
3125 {
3126 return RETURN_ERR;
3127 }
3128 }
3129 strcpy(temp_output,"");
3130 temp = strtok(temp_TransmitRates,",");
3131 while(temp!=NULL)
3132 {
3133 strcpy(temp1,temp);
3134 if(radioIndex==1)
3135 {
3136 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3137 {
3138 return RETURN_ERR;
3139 }
3140 }
3141
3142 if(strcmp(temp,"5.5")==0)
3143 {
3144 strcpy(temp1,"55");
3145 }
3146 else
3147 {
3148 strcat(temp1,"0");
3149 }
3150 strcat(temp_output,temp1);
3151 temp = strtok(NULL,",");
3152 if(temp!=NULL)
3153 {
3154 strcat(temp_output," ");
3155 }
3156 }
3157 strcpy(TransmitRates,temp_output);
3158
3159 params.name= "basic_rates";
3160 params.value =TransmitRates;
3161
3162 wifi_dbg_printf("\n%s:",__func__);
3163 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3164 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3165 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3166 wifi_hostapdWrite(config_file,&params,1);
3167 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3168 return RETURN_OK;
3169}
3170
3171//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3172INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3173{
3174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3175 FILE *fp = NULL;
3176 char path[256] = {0}, output_string[256] = {0};
3177 int count = 0;
3178 char *interface = NULL;
3179
3180 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3181 if (fp == NULL)
3182 {
3183 printf("Failed to run command in Function %s\n", __FUNCTION__);
3184 return RETURN_ERR;
3185 }
3186 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3187 {
3188 interface = strchr(path, '=');
3189
3190 if (interface != NULL)
3191 {
3192 strcpy(output_string, interface + 1);
3193 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3194 interface_name[count] = output_string[count];
3195
3196 interface_name[count] = '\0';
3197 }
3198 }
3199 pclose(fp);
3200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3201 return RETURN_OK;
3202}
3203
3204INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3205{
3206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3207 output_struct->radio_BytesSent = 0;
3208 output_struct->radio_BytesReceived = 0;
3209 output_struct->radio_PacketsSent = 0;
3210 output_struct->radio_PacketsReceived = 0;
3211 output_struct->radio_ErrorsSent = 0;
3212 output_struct->radio_ErrorsReceived = 0;
3213 output_struct->radio_DiscardPacketsSent = 0;
3214 output_struct->radio_DiscardPacketsReceived = 0;
3215 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3216 return RETURN_OK;
3217}
3218
3219
3220INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3221{
3222 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3223 CHAR buf[MAX_CMD_SIZE] = {0};
3224 CHAR Value[MAX_BUF_SIZE] = {0};
3225 FILE *fp = NULL;
3226
3227 if (ifname == NULL || strlen(ifname) <= 1)
3228 return RETURN_OK;
3229
3230 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3231 system(buf);
3232
3233 fp = fopen("/tmp/Radio_Stats.txt", "r");
3234 if(fp == NULL)
3235 {
3236 printf("/tmp/Radio_Stats.txt not exists \n");
3237 return RETURN_ERR;
3238 }
3239 fclose(fp);
3240
3241 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3242 File_Reading(buf, Value);
3243 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3244
3245 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3246 File_Reading(buf, Value);
3247 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3248
3249 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3250 File_Reading(buf, Value);
3251 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3252
3253 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3254 File_Reading(buf, Value);
3255 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3256
3257 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3258 File_Reading(buf, Value);
3259 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3260
3261 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3262 File_Reading(buf, Value);
3263 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3264
3265 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3266 File_Reading(buf, Value);
3267 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3268
3269 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3270 File_Reading(buf, Value);
3271 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3272
3273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3274 return RETURN_OK;
3275}
3276
3277INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3278{
3279 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3280 CHAR buf[MAX_CMD_SIZE] = {0};
3281 FILE *fp = NULL;
3282 INT count = 0;
3283
3284 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3285 {
3286 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3287 File_Reading(buf, status);
3288 }
3289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3290 return RETURN_OK;
3291}
3292
3293//Get detail radio traffic static info
3294INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3295{
3296
3297#if 0
3298 //ifconfig radio_x
3299 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3300 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3301 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3302 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3303
3304 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3305 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3306 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.
3307 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.
3308
3309 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3310 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].
3311 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3312 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.
3313 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
3314 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
3315 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
3316 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
3317 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
3318
3319 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
3320 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
3321 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
3322 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.
3323
3324 return RETURN_OK;
3325#endif
3326
developera91d99f2022-09-29 15:59:10 +08003327 CHAR interface_name[64] = {0};
3328 CHAR config_path[64] = {0};
3329 BOOL iface_status = FALSE;
3330 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003331
3332 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3333 if (NULL == output_struct)
3334 return RETURN_ERR;
3335
developera91d99f2022-09-29 15:59:10 +08003336 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3337 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003338
developera91d99f2022-09-29 15:59:10 +08003339 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003340
developera91d99f2022-09-29 15:59:10 +08003341 if (iface_status == TRUE)
3342 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3343 else
3344 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003345
developera91d99f2022-09-29 15:59:10 +08003346 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3347 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3348 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3349 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3350 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3351 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3352 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3353 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003354
3355 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3356 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].
3357 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3358 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.
3359 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
3360 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
3361 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
3362 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
3363 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
3364
3365 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
3366 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
3367 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
3368 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.
3369
3370 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3371
3372 return RETURN_OK;
3373}
3374
3375//Set radio traffic static Measureing rules
3376INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3377{
3378 //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
3379 // Else, save the MeasuringRate and MeasuringInterval for future usage
3380
3381 return RETURN_OK;
3382}
3383
3384//To start or stop RadioTrafficStats
3385INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3386{
3387 //zqiu: If the RadioTrafficStats process running
3388 // if(enable)
3389 // return RETURN_OK.
3390 // else
3391 // Stop RadioTrafficStats process
3392 // Else
3393 // if(enable)
3394 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3395 // else
3396 // return RETURN_OK.
3397
3398 return RETURN_OK;
3399}
3400
3401//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
3402INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3403{
3404 //zqiu: Please ignor signalIndex.
3405 if (NULL == SignalLevel)
3406 return RETURN_ERR;
3407 *SignalLevel=(radioIndex==0)?-19:-19;
3408
3409 return RETURN_OK;
3410}
3411
3412//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3413INT wifi_applyRadioSettings(INT radioIndex)
3414{
3415 return RETURN_OK;
3416}
3417
3418//Get the radio index assocated with this SSID entry
3419INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3420{
3421 if (NULL == radioIndex)
3422 return RETURN_ERR;
3423 *radioIndex=ssidIndex%2;
3424
3425 return RETURN_OK;
3426}
3427
3428//Device.WiFi.SSID.{i}.Enable
3429//Get SSID enable configuration parameters (not the SSID enable status)
3430INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3431{
3432 if (NULL == output_bool)
3433 return RETURN_ERR;
3434
3435 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3436 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3437 return wifi_getApEnable(ssidIndex, output_bool);
3438}
3439
3440//Device.WiFi.SSID.{i}.Enable
3441//Set SSID enable configuration parameters
3442INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3443{
3444 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3445 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3446 return wifi_setApEnable(ssidIndex, enable);
3447}
3448
3449//Device.WiFi.SSID.{i}.Status
3450//Get the SSID enable status
3451INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3452{
3453 char cmd[MAX_CMD_SIZE]={0};
3454 char buf[MAX_BUF_SIZE]={0};
3455 BOOL output_bool;
3456
3457 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3458 if (NULL == output_string)
3459 return RETURN_ERR;
3460 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3461 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3462
3463 wifi_getApEnable(ssidIndex,&output_bool);
3464 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3465
3466 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3467 return RETURN_OK;
3468}
3469
3470// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3471INT wifi_getSSIDName(INT apIndex, CHAR *output)
3472{
3473 char config_file[MAX_BUF_SIZE] = {0};
3474
3475 if (NULL == output)
3476 return RETURN_ERR;
3477
3478 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3479 wifi_hostapdRead(config_file,"ssid",output,32);
3480
3481 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3482 return RETURN_OK;
3483}
3484
3485// Set a max 32 byte string and sets an internal variable to the SSID name
3486INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3487{
3488 char str[MAX_BUF_SIZE]={'\0'};
3489 char cmd[MAX_CMD_SIZE]={'\0'};
3490 struct params params;
3491 char config_file[MAX_BUF_SIZE] = {0};
3492
3493 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3494 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3495 return RETURN_ERR;
3496
3497 params.name = "ssid";
3498 params.value = ssid_string;
3499 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3500 wifi_hostapdWrite(config_file, &params, 1);
3501 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3502 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3503
3504 return RETURN_OK;
3505}
3506
3507//Get the BSSID
3508INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3509{
3510 char cmd[MAX_CMD_SIZE]="";
3511
3512 if (NULL == output_string)
3513 return RETURN_ERR;
3514
3515 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3516 {
3517 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3518 _syscmd(cmd, output_string, 64);
3519 return RETURN_OK;
3520 }
3521 strncpy(output_string, "\0", 1);
3522
3523 return RETURN_ERR;
3524}
3525
3526//Get the MAC address associated with this Wifi SSID
3527INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3528{
3529 wifi_getBaseBSSID(ssidIndex,output_string);
3530 return RETURN_OK;
3531}
3532
3533//Get the basic SSID traffic static info
3534//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3535//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3536INT wifi_applySSIDSettings(INT ssidIndex)
3537{
3538 BOOL status = false;
3539 char cmd[MAX_CMD_SIZE] = {0};
3540 char buf[MAX_CMD_SIZE] = {0};
3541 int apIndex, ret;
3542 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3543
3544 wifi_getApEnable(ssidIndex,&status);
3545 // Do not apply when ssid index is disabled
3546 if (status == false)
3547 return RETURN_OK;
3548
3549 /* Doing full remove and add for ssid Index
3550 * Not all hostapd options are supported with reload
3551 * for example macaddr_acl
3552 */
3553 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3554 return RETURN_ERR;
3555
3556 ret = wifi_setApEnable(ssidIndex,true);
3557
3558 /* Workaround for hostapd issue with multiple bss definitions
3559 * when first created interface will be removed
3560 * then all vaps other vaps on same phy are removed
3561 * after calling setApEnable to false readd all enabled vaps */
3562 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3563 apIndex = 2*i+radioIndex;
3564 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3565 _syscmd(cmd, buf, sizeof(buf));
3566 if(*buf == '1')
3567 wifi_setApEnable(apIndex, true);
3568 }
3569
3570 return ret;
3571}
3572
developera3c68b92022-09-13 15:27:29 +08003573struct channels_noise {
3574 int channel;
3575 int noise;
3576};
3577
3578// Return noise array for each channel
3579int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3580{
3581 FILE *f = NULL;
3582 char cmd[128] = {0};
3583 char *line = NULL;
3584 size_t len = 0;
3585 ssize_t read = 0;
3586 int tmp = 0, arr_index = -1;
3587
3588 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3589
3590 if ((f = popen(cmd, "r")) == NULL) {
3591 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3592 return RETURN_ERR;
3593 }
3594 line = malloc(sizeof(char) * 256);
3595 while((read = getline(&line, &len, f)) != -1) {
3596 sscanf(line, "%d", &tmp);
3597 if (tmp > 0) { // channel frequency, the first line must be frequency
3598 arr_index++;
3599 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3600 } else { // noise
3601 channels_noise_arr[arr_index].noise = tmp;
3602 }
3603 }
3604 free(line);
3605 pclose(f);
3606 return RETURN_OK;
3607}
3608
developer06a01d92022-09-07 16:32:39 +08003609//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3610//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3611INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3612{
developera3c68b92022-09-13 15:27:29 +08003613 int index = -1;
3614 wifi_neighbor_ap2_t *scan_array = NULL;
3615 char cmd[256]={0};
3616 char buf[128]={0};
3617 char file_name[32] = {0};
3618 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003619 char line[256] = {0};
3620 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003621 int freq=0;
3622 FILE *f = NULL;
3623 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003624 int channels_num = 0;
3625 int vht_channel_width = 0;
3626 bool get_nosie_ret = false;
3627 bool filter_enable = false;
3628 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003629
developer615510b2022-09-27 10:14:35 +08003630 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003631
3632 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3633 f = fopen(file_name, "r");
3634 if (f != NULL) {
3635 fgets(filter_SSID, sizeof(file_name), f);
3636 if (strlen(filter_SSID) != 0)
3637 filter_enable = true;
3638 fclose(f);
3639 }
3640
3641 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003642 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003643 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003644
developera3c68b92022-09-13 15:27:29 +08003645 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3646 get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer06a01d92022-09-07 16:32:39 +08003647
developera3c68b92022-09-13 15:27:29 +08003648 sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
developer615510b2022-09-27 10:14:35 +08003649 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
developera3c68b92022-09-13 15:27:29 +08003650 fprintf(stderr, "cmd: %s\n", cmd);
3651 if ((f = popen(cmd, "r")) == NULL) {
3652 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3653 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003654 }
developer615510b2022-09-27 10:14:35 +08003655 ret = fgets(line, sizeof(line), f);
3656 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003657 if(strstr(line, "BSS") != NULL) { // new neighbor info
3658 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3659 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3660 // 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 +08003661
developera3c68b92022-09-13 15:27:29 +08003662 if (!filter_BSS) {
3663 index++;
3664 wifi_neighbor_ap2_t *tmp;
3665 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3666 if (tmp == NULL) { // no more memory to use
3667 index--;
3668 wifi_dbg_printf("%s: realloc failed\n", __func__);
3669 break;
3670 }
3671 scan_array = tmp;
3672 }
3673 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3674
3675 filter_BSS = false;
3676 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3677 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3678 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3679 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3680 } else if (strstr(line, "freq") != NULL) {
3681 sscanf(line," freq: %d", &freq);
3682 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3683
3684 if (freq >= 2412 && freq <= 2484) {
3685 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3686 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3687 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3688 }
3689 else if (freq >= 5160 && freq <= 5805) {
3690 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3691 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3692 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3693 }
3694
3695 scan_array[index].ap_Noise = 0;
3696 if (get_nosie_ret) {
3697 for (int i = 0; i < channels_num; i++) {
3698 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3699 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3700 break;
3701 }
3702 }
3703 }
3704 } else if (strstr(line, "beacon interval") != NULL) {
3705 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3706 } else if (strstr(line, "signal") != NULL) {
3707 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3708 } else if (strstr(line,"SSID") != NULL) {
3709 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3710 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3711 filter_BSS = true;
3712 }
3713 } else if (strstr(line, "Supported rates") != NULL) {
3714 char SRate[80] = {0}, *tmp = NULL;
3715 memset(buf, 0, sizeof(buf));
3716 strcpy(SRate, line);
3717 tmp = strtok(SRate, ":");
3718 tmp = strtok(NULL, ":");
3719 strcpy(buf, tmp);
3720 memset(SRate, 0, sizeof(SRate));
3721
3722 tmp = strtok(buf, " \n");
3723 while (tmp != NULL) {
3724 strcat(SRate, tmp);
3725 if (SRate[strlen(SRate) - 1] == '*') {
3726 SRate[strlen(SRate) - 1] = '\0';
3727 }
3728 strcat(SRate, ",");
3729
3730 tmp = strtok(NULL, " \n");
3731 }
3732 SRate[strlen(SRate) - 1] = '\0';
3733 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3734 } else if (strstr(line, "DTIM") != NULL) {
3735 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3736 } else if (strstr(line, "VHT capabilities") != NULL) {
3737 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3738 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3739 } else if (strstr(line, "HT capabilities") != NULL) {
3740 strcat(scan_array[index].ap_SupportedStandards, ",n");
3741 strcpy(scan_array[index].ap_OperatingStandards, "n");
3742 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003743 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003744 sscanf(line," * channel width: %d", &vht_channel_width);
3745 if(vht_channel_width == 1) {
3746 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3747 } else {
3748 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3749 }
3750 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3751 continue;
3752 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003753 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003754 sscanf(line," * secondary channel offset: %s", &buf);
3755 if (!strcmp(buf, "above")) {
3756 //40Mhz +
3757 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3758 }
3759 else if (!strcmp(buf, "below")) {
3760 //40Mhz -
3761 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3762 } else {
3763 //20Mhz
3764 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3765 }
3766 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3767 continue;
3768 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003769 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3770 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3771 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003772 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3773 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003774 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003775 else
developer615510b2022-09-27 10:14:35 +08003776 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003777 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003778 if (strstr(line, "HE80/5GHz") != NULL) {
3779 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3780 ret = fgets(line, sizeof(line), f);
3781 } else
3782 continue;
developera3c68b92022-09-13 15:27:29 +08003783 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003784 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003785 }
developer615510b2022-09-27 10:14:35 +08003786 continue;
developera3c68b92022-09-13 15:27:29 +08003787 } else if (strstr(line, "WPA") != NULL) {
3788 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3789 } else if (strstr(line, "RSN") != NULL) {
3790 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3791 } else if (strstr(line, "Group cipher") != NULL) {
3792 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3793 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3794 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3795 }
3796 }
developer615510b2022-09-27 10:14:35 +08003797 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003798 }
3799
3800 if (!filter_BSS) {
3801 *output_array_size = index + 1;
3802 } else {
3803 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3804 *output_array_size = index;
3805 }
3806 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003807 pclose(f);
developer06a01d92022-09-07 16:32:39 +08003808 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003809 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003810}
3811
3812//>> Deprecated: used for old RDKB code.
3813INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3814{
3815 INT status = RETURN_ERR;
3816
3817 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3818 output_struct->wifi_PLCPErrorCount = 0;
3819 output_struct->wifi_FCSErrorCount = 0;
3820 output_struct->wifi_InvalidMACCount = 0;
3821 output_struct->wifi_PacketsOtherReceived = 0;
3822 output_struct->wifi_Noise = 0;
3823 status = RETURN_OK;
3824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3825 return status;
3826}
3827
3828INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3829{
3830 char cmd[128];
3831 char buf[1280];
3832 char *pos = NULL;
3833
3834 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3835 if (NULL == output_struct)
3836 return RETURN_ERR;
3837
3838 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3839
3840 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3841 _syscmd(cmd, buf, sizeof(buf));
3842
3843 pos = buf;
3844 if ((pos = strstr(pos, "RX packets:")) == NULL)
3845 return RETURN_ERR;
3846 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3847
3848 if ((pos = strstr(pos, "TX packets:")) == NULL)
3849 return RETURN_ERR;
3850 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3851
3852 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3853 return RETURN_ERR;
3854 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3855
3856 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3857 return RETURN_ERR;
3858 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3859
3860 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3861 _syscmd(cmd, buf, sizeof(buf));
3862 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3863
3864#if 0
3865 //TODO: need to revisit below implementation
3866 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3867 char interface_name[MAX_BUF_SIZE] = {0};
3868 char interface_status[MAX_BUF_SIZE] = {0};
3869 char Value[MAX_BUF_SIZE] = {0};
3870 char buf[MAX_CMD_SIZE] = {0};
3871 char cmd[MAX_CMD_SIZE] = {0};
3872 FILE *fp = NULL;
3873
3874 if (NULL == output_struct) {
3875 return RETURN_ERR;
3876 }
3877
3878 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3879
3880 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3881 {
3882 if(apIndex == 0) //private_wifi for 2.4G
3883 {
3884 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3885 }
3886 else if(apIndex == 1) //private_wifi for 5G
3887 {
3888 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3889 }
3890 else if(apIndex == 4) //public_wifi for 2.4G
3891 {
3892 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3893 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3894 {
3895 return RETURN_ERR;
3896 }
3897 if(buf[0] == '#')//tp-link
3898 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3899 else//tenda
3900 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3901 }
3902 else if(apIndex == 5) //public_wifi for 5G
3903 {
3904 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3905 }
3906
3907 GetIfacestatus(interface_name, interface_status);
3908
3909 if(0 != strcmp(interface_status, "1"))
3910 return RETURN_ERR;
3911
3912 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3913 system(cmd);
3914
3915 fp = fopen("/tmp/SSID_Stats.txt", "r");
3916 if(fp == NULL)
3917 {
3918 printf("/tmp/SSID_Stats.txt not exists \n");
3919 return RETURN_ERR;
3920 }
3921 fclose(fp);
3922
3923 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3924 File_Reading(buf, Value);
3925 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3926
3927 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3928 File_Reading(buf, Value);
3929 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3930
3931 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3932 File_Reading(buf, Value);
3933 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3934
3935 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3936 File_Reading(buf, Value);
3937 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3938
3939 /* There is no specific parameter from caller to associate the value wifi_Associations */
3940 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3941 //_syscmd(cmd, buf, sizeof(buf));
3942 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3943 }
3944#endif
3945 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3946 return RETURN_OK;
3947}
3948
3949INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3950{
3951 char interface_name[MAX_BUF_SIZE] = {0};
3952 char interface_status[MAX_BUF_SIZE] = {0};
3953 char Value[MAX_BUF_SIZE] = {0};
3954 char buf[MAX_CMD_SIZE] = {0};
3955 char cmd[MAX_CMD_SIZE] = {0};
3956 FILE *fp = NULL;
3957
3958 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3959 if (NULL == output_struct)
3960 return RETURN_ERR;
3961
3962 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3963
3964 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3965 {
3966 if(apIndex == 0) //private_wifi for 2.4G
3967 {
3968 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3969 }
3970 else if(apIndex == 1) //private_wifi for 5G
3971 {
3972 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3973 }
3974 else if(apIndex == 4) //public_wifi for 2.4G
3975 {
3976 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3977 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3978 {
3979 return RETURN_ERR;
3980 }
3981 if(buf[0] == '#')
3982 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3983 else
3984 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3985 }
3986 else if(apIndex == 5) //public_wifi for 5G
3987 {
3988 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3989 }
3990
3991 GetIfacestatus(interface_name, interface_status);
3992
3993 if(0 != strcmp(interface_status, "1"))
3994 return RETURN_ERR;
3995
3996 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3997 system(cmd);
3998
3999 fp = fopen("/tmp/SSID_Stats.txt", "r");
4000 if(fp == NULL)
4001 {
4002 printf("/tmp/SSID_Stats.txt not exists \n");
4003 return RETURN_ERR;
4004 }
4005 fclose(fp);
4006
4007 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4008 File_Reading(buf, Value);
4009 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4010
4011 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4012 File_Reading(buf, Value);
4013 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4014
4015 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4016 File_Reading(buf, Value);
4017 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4018
4019 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4020 File_Reading(buf, Value);
4021 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4022 }
4023
4024 output_struct->wifi_UnicastPacketsSent = 0;
4025 output_struct->wifi_UnicastPacketsReceived = 0;
4026 output_struct->wifi_MulticastPacketsSent = 0;
4027 output_struct->wifi_MulticastPacketsReceived = 0;
4028 output_struct->wifi_BroadcastPacketsSent = 0;
4029 output_struct->wifi_BroadcastPacketsRecevied = 0;
4030 output_struct->wifi_UnknownPacketsReceived = 0;
4031
4032 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4033 return RETURN_OK;
4034}
4035
4036INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4037{
4038 INT status = RETURN_ERR;
4039
4040 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4041 //Below values should get updated from hal
4042 output_struct->wifi_RetransCount=0;
4043 output_struct->wifi_FailedRetransCount=0;
4044 output_struct->wifi_RetryCount=0;
4045 output_struct->wifi_MultipleRetryCount=0;
4046 output_struct->wifi_ACKFailureCount=0;
4047 output_struct->wifi_AggregatedPacketCount=0;
4048
4049 status = RETURN_OK;
4050 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4051
4052 return status;
4053}
4054
4055INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4056{
4057 INT status = RETURN_ERR;
4058 UINT index;
4059 wifi_neighbor_ap_t *pt=NULL;
4060
4061 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4062 *output_array_size=2;
4063 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4064 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4065 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4066 strcpy(pt->ap_Radio,"");
4067 strcpy(pt->ap_SSID,"");
4068 strcpy(pt->ap_BSSID,"");
4069 strcpy(pt->ap_Mode,"");
4070 pt->ap_Channel=1;
4071 pt->ap_SignalStrength=0;
4072 strcpy(pt->ap_SecurityModeEnabled,"");
4073 strcpy(pt->ap_EncryptionMode,"");
4074 strcpy(pt->ap_OperatingFrequencyBand,"");
4075 strcpy(pt->ap_SupportedStandards,"");
4076 strcpy(pt->ap_OperatingStandards,"");
4077 strcpy(pt->ap_OperatingChannelBandwidth,"");
4078 pt->ap_BeaconPeriod=1;
4079 pt->ap_Noise=0;
4080 strcpy(pt->ap_BasicDataTransferRates,"");
4081 strcpy(pt->ap_SupportedDataTransferRates,"");
4082 pt->ap_DTIMPeriod=1;
4083 pt->ap_ChannelUtilization = 1;
4084 }
4085
4086 status = RETURN_OK;
4087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4088
4089 return status;
4090}
4091
4092//----------------- AP HAL -------------------------------
4093
4094//>> Deprecated: used for old RDKB code.
4095INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4096{
4097 if (NULL == output_ulong || NULL == output_struct)
4098 return RETURN_ERR;
4099 *output_ulong = 0;
4100 *output_struct = NULL;
4101 return RETURN_OK;
4102}
4103
4104#ifdef HAL_NETLINK_IMPL
4105static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4106 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4107 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4108 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4109 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4110 char mac_addr[20];
4111 static int count=0;
4112 int rate=0;
4113
4114 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4115
4116 nla_parse(tb,
4117 NL80211_ATTR_MAX,
4118 genlmsg_attrdata(gnlh, 0),
4119 genlmsg_attrlen(gnlh, 0),
4120 NULL);
4121
4122 if(!tb[NL80211_ATTR_STA_INFO]) {
4123 fprintf(stderr, "sta stats missing!\n");
4124 return NL_SKIP;
4125 }
4126
4127
4128 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4129 fprintf(stderr, "failed to parse nested attributes!\n");
4130 return NL_SKIP;
4131 }
4132
4133 //devIndex starts from 1
4134 if( ++count == out->wifi_devIndex )
4135 {
4136 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4137 //Getting the mac addrress
4138 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4139
4140 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4141 fprintf(stderr, "failed to parse nested rate attributes!");
4142 return NL_SKIP;
4143 }
4144
4145 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4146 if(rinfo[NL80211_RATE_INFO_BITRATE])
4147 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4148 out->wifi_devTxRate = rate/10;
4149 }
4150
4151 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4152 fprintf(stderr, "failed to parse nested rate attributes!");
4153 return NL_SKIP;
4154 }
4155
4156 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4157 if(rinfo[NL80211_RATE_INFO_BITRATE])
4158 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4159 out->wifi_devRxRate = rate/10;
4160 }
4161 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4162 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4163
4164 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4165 count = 0; //starts the count for next cycle
4166 return NL_STOP;
4167 }
4168
4169 return NL_SKIP;
4170
4171}
4172#endif
4173
4174INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4175{
4176#ifdef HAL_NETLINK_IMPL
4177 Netlink nl;
4178 char if_name[10];
4179
4180 wifi_device_info_t info;
4181 info.wifi_devIndex = devIndex;
4182
4183 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4184
4185 nl.id = initSock80211(&nl);
4186
4187 if (nl.id < 0) {
4188 fprintf(stderr, "Error initializing netlink \n");
4189 return -1;
4190 }
4191
4192 struct nl_msg* msg = nlmsg_alloc();
4193
4194 if (!msg) {
4195 fprintf(stderr, "Failed to allocate netlink message.\n");
4196 nlfree(&nl);
4197 return -2;
4198 }
4199
4200 genlmsg_put(msg,
4201 NL_AUTO_PORT,
4202 NL_AUTO_SEQ,
4203 nl.id,
4204 0,
4205 NLM_F_DUMP,
4206 NL80211_CMD_GET_STATION,
4207 0);
4208
4209 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4210 nl_send_auto(nl.socket, msg);
4211 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4212 nl_recvmsgs(nl.socket, nl.cb);
4213 nlmsg_free(msg);
4214 nlfree(&nl);
4215
4216 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4217 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4218 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4219 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4220 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4221 return RETURN_OK;
4222#else
4223 //iw utility to retrieve station information
4224#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4225#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4226#define MACFILE "/tmp/wifi_AssoMac.txt"
4227#define TXRATEFILE "/tmp/wifi_txrate.txt"
4228#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4229 FILE *file = NULL;
4230 char if_name[10] = {'\0'};
4231 char pipeCmd[256] = {'\0'};
4232 char line[256];
4233 int count,device = 0;
4234
4235 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4236
4237 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4238 file = popen(pipeCmd, "r");
4239
4240 if(file == NULL)
4241 return RETURN_ERR; //popen failed
4242
4243 fgets(line, sizeof line, file);
4244 device = atoi(line);
4245 pclose(file);
4246
4247 if(device == 0)
4248 return RETURN_ERR; //No devices are connected
4249
4250 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4251 system(pipeCmd);
4252
4253 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4254
4255 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4256
4257 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4258
4259 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4260
4261 //devIndex starts from 1, ++count
4262 if((file = fopen(SIGNALFILE, "r")) != NULL )
4263 {
4264 for(count =0;fgets(line, sizeof line, file) != NULL;)
4265 {
4266 if (++count == devIndex)
4267 {
4268 output_struct->wifi_devSignalStrength = atoi(line);
4269 break;
4270 }
4271 }
4272 fclose(file);
4273 }
4274 else
4275 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4276
4277 if((file = fopen(MACFILE, "r")) != NULL )
4278 {
4279 for(count =0;fgets(line, sizeof line, file) != NULL;)
4280 {
4281 if (++count == devIndex)
4282 {
4283 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]);
4284 break;
4285 }
4286 }
4287 fclose(file);
4288 }
4289 else
4290 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4291
4292 if((file = fopen(TXRATEFILE, "r")) != NULL )
4293 {
4294 for(count =0;fgets(line, sizeof line, file) != NULL;)
4295 {
4296 if (++count == devIndex)
4297 {
4298 output_struct->wifi_devTxRate = atoi(line);
4299 break;
4300 }
4301 }
4302 fclose(file);
4303 }
4304 else
4305 fprintf(stderr,"fopen wifi_txrate.txt failed");
4306
4307 if((file = fopen(RXRATEFILE, "r")) != NULL)
4308 {
4309 for(count =0;fgets(line, sizeof line, file) != NULL;)
4310 {
4311 if (++count == devIndex)
4312 {
4313 output_struct->wifi_devRxRate = atoi(line);
4314 break;
4315 }
4316 }
4317 fclose(file);
4318 }
4319 else
4320 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4321
4322 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4323
4324 return RETURN_OK;
4325#endif
4326}
4327
4328INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4329{
4330 if (NULL == device)
4331 return RETURN_ERR;
4332 return RETURN_OK;
4333}
4334//<<
4335
4336
4337//--------------wifi_ap_hal-----------------------------
4338//enables CTS protection for the radio used by this AP
4339INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4340{
4341 //save config and Apply instantly
4342 return RETURN_ERR;
4343}
4344
4345// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4346INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4347{
developer463d39a2022-09-13 15:32:51 +08004348 char config_file[64] = {'\0'};
4349 char buf[64] = {'\0'};
4350 struct params list;
4351
4352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4353 list.name = "ht_coex";
4354 snprintf(buf, sizeof(buf), "%d", enable);
4355 list.value = buf;
4356
4357 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4358 wifi_hostapdWrite(config_file, &list, 1);
4359 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4360
4361 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4362
4363 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004364}
4365
4366//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4367INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4368{
developerea4bcce2022-09-13 15:26:13 +08004369 char config_file[MAX_BUF_SIZE] = {'\0'};
4370 char buf[MAX_BUF_SIZE] = {'\0'};
4371 struct params list;
4372
4373 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4374 if (threshold < 256 || threshold > 2346 )
4375 return RETURN_ERR;
4376 list.name = "fragm_threshold";
4377 snprintf(buf, sizeof(buf), "%d", threshold);
4378 list.value = buf;
4379
4380 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4381 wifi_hostapdWrite(config_file, &list, 1);
4382 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004383
developerea4bcce2022-09-13 15:26:13 +08004384 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004385
4386 return RETURN_OK;
4387}
4388
4389// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4390INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4391{
developer51a927d2022-09-13 15:42:22 +08004392 char config_file[64] = {'\0'};
4393 char cmd[128] = {'\0'};
4394 char buf[64] = {'\0'};
4395 char stbc_config[16] = {'\0'};
4396 wifi_band band;
4397 int iterator = 0;
4398 BOOL current_stbc = FALSE;
4399
4400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4401
4402 band = wifi_index_to_band(radioIndex);
4403 if (band == band_invalid)
4404 return RETURN_ERR;
4405
4406 if (band == band_2_4)
4407 iterator = 1;
4408 else if (band == band_5)
4409 iterator = 2;
4410 else
4411 return RETURN_OK;
4412
4413 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4414
4415 // set ht and vht config
4416 for (int i = 0; i < iterator; i++) {
4417 memset(stbc_config, 0, sizeof(stbc_config));
4418 memset(cmd, 0, sizeof(cmd));
4419 memset(buf, 0, sizeof(buf));
4420 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4421 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4422 _syscmd(cmd, buf, sizeof(buf));
4423 if (strlen(buf) != 0)
4424 current_stbc = TRUE;
4425 if (current_stbc == STBC_Enable)
4426 continue;
4427
4428 if (STBC_Enable == TRUE) {
4429 // Append the STBC flags in capab config
4430 memset(cmd, 0, sizeof(cmd));
4431 if (i == 0)
4432 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4433 else
4434 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4435 _syscmd(cmd, buf, sizeof(buf));
4436 } else if (STBC_Enable == FALSE) {
4437 // Remove the STBC flags and remain other flags in capab
4438 memset(cmd, 0, sizeof(cmd));
4439 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4440 _syscmd(cmd, buf, sizeof(buf));
4441 memset(cmd, 0, sizeof(cmd));
4442 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4443 _syscmd(cmd, buf, sizeof(buf));
4444 }
4445 }
4446
4447 wifi_reloadAp(radioIndex);
4448
4449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4450 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004451}
4452
4453// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4454INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4455{
developer54e6b9f2022-09-28 14:41:20 +08004456 char AMSDU_file_path[64] = {0};
4457
4458 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4459
4460 if(output_bool == NULL)
4461 return RETURN_ERR;
4462
4463 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4464
4465 if (access(AMSDU_file_path, F_OK) == 0)
4466 *output_bool = TRUE;
4467 else
4468 *output_bool = FALSE;
4469
4470 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4471 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004472}
4473
4474// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4475INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4476{
developer54e6b9f2022-09-28 14:41:20 +08004477 char cmd[64]={0};
4478 char buf[64]={0};
4479 char AMSDU_file_path[64] = {0};
4480
4481 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4482
4483 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4484 _syscmd(cmd, buf, sizeof(buf));
4485
4486 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4487 memset(cmd, 0, sizeof(cmd));
4488 if (amsduEnable == TRUE)
4489 sprintf(cmd, "touch %s", AMSDU_file_path);
4490 else
4491 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4492 _syscmd(cmd, buf, sizeof(buf));
4493
4494 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4495 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004496}
4497
4498//P2 // outputs the number of Tx streams
4499INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4500{
developer2de97692022-09-26 14:00:03 +08004501 char buf[8] = {0};
4502 char cmd[128] = {0};
4503
4504 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4505
4506 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4507 _syscmd(cmd, buf, sizeof(buf));
4508
4509 // if there is no record, output the max number of spatial streams
4510 if (strlen(buf) == 0) {
4511 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4512 _syscmd(cmd, buf, sizeof(buf));
4513 }
4514
4515 *output_int = (INT)strtol(buf, NULL, 10);
4516
4517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4518
4519 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004520}
4521
4522//P2 // sets the number of Tx streams to an enviornment variable
4523INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4524{
developer2de97692022-09-26 14:00:03 +08004525 char cmd[128] = {0};
4526 char buf[128] = {0};
4527 char chain_mask_file[128] = {0};
4528 FILE *f = NULL;
4529
4530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4531
4532 if (numStreams == 0) {
4533 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4534 return RETURN_ERR;
4535 }
4536 wifi_setRadioEnable(radioIndex, FALSE);
4537 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4538 _syscmd(cmd, buf, sizeof(buf));
4539
4540 if (strlen(buf) > 0) {
4541 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4542 return RETURN_ERR;
4543 }
4544 wifi_setRadioEnable(radioIndex, TRUE);
4545
4546 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4547 f = fopen(chain_mask_file, "w");
4548 if (f == NULL) {
4549 fprintf(stderr, "%s: fopen failed.\n", __func__);
4550 return RETURN_ERR;
4551 }
4552 fprintf(f, "%d", numStreams);
4553 fclose(f);
4554 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4555 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004556}
4557
4558//P2 // outputs the number of Rx streams
4559INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4560{
developer2de97692022-09-26 14:00:03 +08004561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4562 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4563 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004564 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004565 }
4566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004567 return RETURN_OK;
4568}
4569
4570//P2 // sets the number of Rx streams to an enviornment variable
4571INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4572{
developer2de97692022-09-26 14:00:03 +08004573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4574 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4575 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4576 return RETURN_ERR;
4577 }
4578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004579 return RETURN_ERR;
4580}
4581
4582//Get radio RDG enable setting
4583INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4584{
4585 if (NULL == output_bool)
4586 return RETURN_ERR;
4587 *output_bool = TRUE;
4588 return RETURN_OK;
4589}
4590
4591//Get radio RDG enable setting
4592INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4593{
4594 if (NULL == output_bool)
4595 return RETURN_ERR;
4596 *output_bool = TRUE;
4597 return RETURN_OK;
4598}
4599
4600//Set radio RDG enable setting
4601INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4602{
4603 return RETURN_ERR;
4604}
4605
4606//Get radio ADDBA enable setting
4607INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4608{
4609 if (NULL == output_bool)
4610 return RETURN_ERR;
4611 *output_bool = TRUE;
4612 return RETURN_OK;
4613}
4614
4615//Set radio ADDBA enable setting
4616INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4617{
4618 return RETURN_ERR;
4619}
4620
4621//Get radio auto block ack enable setting
4622INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4623{
4624 if (NULL == output_bool)
4625 return RETURN_ERR;
4626 *output_bool = TRUE;
4627 return RETURN_OK;
4628}
4629
4630//Set radio auto block ack enable setting
4631INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4632{
4633 return RETURN_ERR;
4634}
4635
4636//Get radio 11n pure mode enable support
4637INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4638{
4639 if (NULL == output_bool)
4640 return RETURN_ERR;
4641 *output_bool = TRUE;
4642 return RETURN_OK;
4643}
4644
4645//Get radio 11n pure mode enable setting
4646INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4647{
4648 if (NULL == output_bool)
4649 return RETURN_ERR;
4650 *output_bool = TRUE;
4651 return RETURN_OK;
4652}
4653
4654//Set radio 11n pure mode enable setting
4655INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4656{
4657 return RETURN_ERR;
4658}
4659
4660//Get radio IGMP snooping enable setting
4661INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4662{
developer81bf2ed2022-09-13 15:31:14 +08004663 char cmd[128]={0};
4664 char buf[4]={0};
4665 bool bridge = FALSE, mac80211 = FALSE;
4666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4667
4668 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004669 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004670
4671 *output_bool = FALSE;
4672
4673 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4674 _syscmd(cmd, buf, sizeof(buf));
4675 if (strncmp(buf, "1", 1) == 0)
4676 bridge = TRUE;
4677
4678 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4679 _syscmd(cmd, buf, sizeof(buf));
4680 if (strncmp(buf, "1", 1) == 0)
4681 mac80211 = TRUE;
4682
4683 if (bridge && mac80211)
4684 *output_bool = TRUE;
4685
4686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004687 return RETURN_OK;
4688}
4689
4690//Set radio IGMP snooping enable setting
4691INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4692{
developer81bf2ed2022-09-13 15:31:14 +08004693 char cmd[128]={0};
4694 char buf[4]={0};
4695
4696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4697
4698 // bridge
4699 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4700 _syscmd(cmd, buf, sizeof(buf));
4701
4702 // mac80211
4703 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4704 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4705 _syscmd(cmd, buf, sizeof(buf));
4706 }
4707 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4708 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004709}
4710
4711//Get the Reset count of radio
4712INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4713{
4714 if (NULL == output_int)
4715 return RETURN_ERR;
4716 *output_int = (radioIndex==0)? 1: 3;
4717
4718 return RETURN_OK;
4719}
4720
4721
4722//---------------------------------------------------------------------------------------------------
4723//
4724// Additional Wifi AP level APIs used for Access Point devices
4725//
4726//---------------------------------------------------------------------------------------------------
4727
4728// creates a new ap and pushes these parameters to the hardware
4729INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4730{
4731 char buf[1024];
4732 char cmd[128];
4733
4734 if (NULL == essid)
4735 return RETURN_ERR;
4736
4737 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4738 _syscmd(cmd, buf, sizeof(buf));
4739
4740 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4741 _syscmd(cmd, buf, sizeof(buf));
4742
4743 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4744
4745 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4746 _syscmd(cmd, buf, sizeof(buf));
4747
4748 return RETURN_OK;
4749}
4750
4751// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4752INT wifi_deleteAp(INT apIndex)
4753{
4754 char buf[1024];
4755 char cmd[128];
4756
4757 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4758 _syscmd(cmd, buf, sizeof(buf));
4759
4760 wifi_removeApSecVaribles(apIndex);
4761
4762 return RETURN_OK;
4763}
4764
4765// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4766INT wifi_getApName(INT apIndex, CHAR *output_string)
4767{
4768 if(NULL == output_string)
4769 return RETURN_ERR;
4770
4771 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4772 return RETURN_OK;
4773}
4774
4775// Outputs the index number in that corresponds to the SSID string
4776INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4777{
4778 CHAR *pos = NULL;
4779
4780 *output_int = -1;
4781 pos = strstr(inputSsidString, AP_PREFIX);
4782 if(pos)
4783 {
4784 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4785 return RETURN_OK;
4786 }
4787 return RETURN_ERR;
4788}
4789
4790INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4791{
4792 return wifi_getIndexFromName(inputSsidString, output_int);
4793}
4794
4795// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4796INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4797{
4798 char buf[MAX_BUF_SIZE] = {0};
4799 char cmd[MAX_CMD_SIZE] = {0};
4800 char config_file[MAX_BUF_SIZE] = {0};
4801
4802 if(NULL == output_string)
4803 return RETURN_ERR;
4804
4805 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4806 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4807 if((strcmp(buf,"3")==0))
4808 snprintf(output_string, 32, "WPAand11i");
4809 else if((strcmp(buf,"2")==0))
4810 snprintf(output_string, 32, "11i");
4811 else if((strcmp(buf,"1")==0))
4812 snprintf(output_string, 32, "WPA");
4813 else
4814 snprintf(output_string, 32, "None");
4815
4816 return RETURN_OK;
4817}
4818
4819// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4820INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4821{
4822 char config_file[MAX_BUF_SIZE] = {0};
4823 struct params list;
4824
4825 if (NULL == beaconTypeString)
4826 return RETURN_ERR;
4827 list.name = "wpa";
4828 list.value = "0";
4829
4830 if((strcmp(beaconTypeString,"WPAand11i")==0))
4831 list.value="3";
4832 else if((strcmp(beaconTypeString,"11i")==0))
4833 list.value="2";
4834 else if((strcmp(beaconTypeString,"WPA")==0))
4835 list.value="1";
4836
4837 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4838 wifi_hostapdWrite(config_file, &list, 1);
4839 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4840 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4841 return RETURN_OK;
4842}
4843
4844// sets the beacon interval on the hardware for this AP
4845INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4846{
developer5f222492022-09-13 15:21:52 +08004847 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4848 struct params params={'\0'};
4849 char buf[MAX_BUF_SIZE] = {'\0'};
4850 char config_file[MAX_BUF_SIZE] = {'\0'};
4851
4852 params.name = "beacon_int";
4853 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4854 params.value = buf;
4855
4856 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4857 wifi_hostapdWrite(config_file, &params, 1);
4858
4859 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4860 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4861 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004862}
4863
4864INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4865{
4866 //save config and apply instantly
4867 return RETURN_ERR;
4868}
4869
4870// Get the packet size threshold supported.
4871INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4872{
4873 //save config and apply instantly
4874 if (NULL == output_bool)
4875 return RETURN_ERR;
4876 *output_bool = FALSE;
4877 return RETURN_OK;
4878}
4879
4880// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4881INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4882{
4883 char cmd[128];
4884 char buf[512];
4885
4886 if (threshold > 0)
4887 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4888 else
4889 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4890 _syscmd(cmd, buf, sizeof(buf));
4891
4892 return RETURN_OK;
4893}
4894
4895// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4896INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4897{
4898 if (NULL == output_string)
4899 return RETURN_ERR;
4900 snprintf(output_string, 32, "TKIPandAESEncryption");
4901 return RETURN_OK;
4902
4903}
4904
4905// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4906INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4907{
4908 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4909 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4910
4911 if(NULL == output_string)
4912 return RETURN_ERR;
4913
4914 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4915 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4916
4917 if(strcmp(buf,"0")==0)
4918 {
4919 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4920 snprintf(output_string, 32, "None");
4921 return RETURN_OK;
4922 }
4923 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4924 param_name = "rsn_pairwise";
4925 else if((strcmp(buf,"1")==0))
4926 param_name = "wpa_pairwise";
4927 else
4928 return RETURN_ERR;
4929 memset(output_string,'\0',32);
4930 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4931 wifi_hostapdRead(config_file,param_name,output_string,32);
4932 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4933
4934 if(strcmp(output_string,"TKIP") == 0)
4935 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4936 else if(strcmp(output_string,"CCMP") == 0)
4937 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4938 else if(strcmp(output_string,"TKIP CCMP") == 0)
4939 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4940
4941 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4942 return RETURN_OK;
4943}
4944
4945// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4946INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4947{
4948 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4949 struct params params={'\0'};
4950 char output_string[32];
4951 char config_file[MAX_BUF_SIZE] = {0};
4952
4953 memset(output_string,'\0',32);
4954 wifi_getApWpaEncryptionMode(apIndex,output_string);
4955
4956 if(strcmp(encMode, "TKIPEncryption") == 0)
4957 params.value = "TKIP";
4958 else if(strcmp(encMode,"AESEncryption") == 0)
4959 params.value = "CCMP";
4960 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4961 params.value = "TKIP CCMP";
4962
4963 if((strcmp(output_string,"WPAand11i")==0))
4964 {
4965 params.name = "wpa_pairwise";
4966 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4967 wifi_hostapdWrite(config_file, &params, 1);
4968 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4969
4970 params.name,"rsn_pairwise";
4971 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4972 wifi_hostapdWrite(config_file, &params, 1);
4973 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4974
4975 return RETURN_OK;
4976 }
4977 else if((strcmp(output_string,"11i")==0))
4978 {
4979 params.name = "rsn_pairwise";
4980 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4981 wifi_hostapdWrite(config_file, &params, 1);
4982 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4983 return RETURN_OK;
4984 }
4985 else if((strcmp(output_string,"WPA")==0))
4986 {
4987 params.name = "wpa_pairwise";
4988 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4989 wifi_hostapdWrite(config_file, &params, 1);
4990 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4991 return RETURN_OK;
4992 }
4993
4994 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4995 return RETURN_OK;
4996}
4997
4998// deletes internal security varable settings for this ap
4999INT wifi_removeApSecVaribles(INT apIndex)
5000{
5001 //TODO: remove the entry in hostapd config file
5002 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5003 //_syscmd(cmd, buf, sizeof(buf));
5004
5005 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5006 //_syscmd(cmd, buf, sizeof(buf));
5007 return RETURN_ERR;
5008}
5009
5010// changes the hardware settings to disable encryption on this ap
5011INT wifi_disableApEncryption(INT apIndex)
5012{
5013 //Apply instantly
5014 return RETURN_ERR;
5015}
5016
5017// set the authorization mode on this ap
5018// mode mapping as: 1: open, 2: shared, 4:auto
5019INT wifi_setApAuthMode(INT apIndex, INT mode)
5020{
developeraf95c502022-09-13 16:18:22 +08005021 struct params params={0};
5022 char config_file[64] = {0};
5023 int ret;
5024
5025 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5026
5027 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5028 params.name = "auth_algs";
5029
5030 if (mode & 1 && mode & 2)
5031 params.value = "3";
5032 else if (mode & 2)
5033 params.value = "2";
5034 else if (mode & 1)
5035 params.value = "1";
5036 else
5037 params.value = "0";
5038
5039 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5040 wifi_hostapdWrite(config_file, &params, 1);
5041 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5042 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5043
5044 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005045}
5046
5047// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5048INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5049{
5050 //save to wifi config, and wait for wifi restart to apply
5051 struct params params={'\0'};
5052 char config_file[MAX_BUF_SIZE] = {0};
5053 int ret;
5054
5055 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5056 if(authMode == NULL)
5057 return RETURN_ERR;
5058
5059 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5060 params.name = "wpa_key_mgmt";
5061
5062 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5063 params.value = "WPA-PSK";
5064 else if(strcmp(authMode,"EAPAuthentication") == 0)
5065 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005066 else if (strcmp(authMode, "SAEAuthentication") == 0)
5067 params.value = "SAE";
5068 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5069 params.value = "WPA-EAP-SUITE-B-192";
developer06a01d92022-09-07 16:32:39 +08005070 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5071 return RETURN_OK; //This is taken careof in beaconType
5072
5073 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5074 ret=wifi_hostapdWrite(config_file,&params,1);
5075 if(!ret)
5076 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5077 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5078
5079 return ret;
5080}
5081
5082// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5083INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5084{
5085 //save to wifi config, and wait for wifi restart to apply
5086 char BeaconType[50] = {0};
5087 char config_file[MAX_BUF_SIZE] = {0};
5088
5089 *authMode = 0;
5090 wifi_getApBeaconType(apIndex,BeaconType);
5091 printf("%s____%s \n",__FUNCTION__,BeaconType);
5092
5093 if(strcmp(BeaconType,"None") == 0)
5094 strcpy(authMode,"None");
5095 else
5096 {
5097 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5098 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5099 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5100 if(strcmp(authMode,"WPA-PSK") == 0)
5101 strcpy(authMode,"SharedAuthentication");
5102 else if(strcmp(authMode,"WPA-EAP") == 0)
5103 strcpy(authMode,"EAPAuthentication");
5104 }
5105
5106 return RETURN_OK;
5107}
5108
5109// Outputs the number of stations associated per AP
5110INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5111{
5112 char cmd[128]={0};
5113 char buf[128]={0};
5114 BOOL status = false;
5115
5116 if(apIndex > MAX_APS)
5117 return RETURN_ERR;
5118
5119 wifi_getApEnable(apIndex,&status);
5120 if (!status)
5121 return RETURN_OK;
5122
5123 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5124 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5125 _syscmd(cmd, buf, sizeof(buf));
5126 sscanf(buf,"%lu", output_ulong);
5127
5128 return RETURN_OK;
5129}
5130
5131// manually removes any active wi-fi association with the device specified on this ap
5132INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5133{
5134 char buf[126]={'\0'};
5135
5136 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5137 system(buf);
5138
5139 return RETURN_OK;
5140}
5141
5142// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5143INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5144{
5145 if(NULL == output_int)
5146 return RETURN_ERR;
5147 *output_int = apIndex%2;
5148 return RETURN_OK;
5149}
5150
5151// sets the radio index for the specific ap
5152INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5153{
5154 //set to config only and wait for wifi reset to apply settings
5155 return RETURN_ERR;
5156}
5157
5158// Get the ACL MAC list per AP
5159INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5160{
5161 char cmd[MAX_CMD_SIZE]={'\0'};
5162 int ret = 0;
5163
5164 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5165 ret = _syscmd(cmd,macArray,buf_size);
5166 if (ret != 0)
5167 return RETURN_ERR;
5168
5169 return RETURN_OK;
5170}
5171
developere6aafda2022-09-13 14:59:28 +08005172INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5173{
5174 char cmd[MAX_CMD_SIZE]={'\0'};
5175 int ret = 0;
5176
5177 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5178 ret = _syscmd(cmd,macArray,buf_size);
5179 if (ret != 0)
5180 return RETURN_ERR;
5181
5182 return RETURN_OK;
5183}
5184
5185
developer06a01d92022-09-07 16:32:39 +08005186// Get the list of stations associated per AP
5187INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5188{
5189 char cmd[128];
5190
5191 if(apIndex > 3) //Currently supporting apIndex upto 3
5192 return RETURN_ERR;
5193 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5194 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5195 _syscmd(cmd, macArray, buf_size);
5196
5197 return RETURN_OK;
5198}
5199
5200// adds the mac address to the filter list
5201//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5202INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5203{
5204 char cmd[MAX_CMD_SIZE]={'\0'};
5205 char buf[MAX_BUF_SIZE]={'\0'};
5206
5207#if 0
5208 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5209 if(_syscmd(cmd,buf,sizeof(buf)))
5210 return RETURN_ERR;
5211#endif
5212 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5213 if(_syscmd(cmd,buf,sizeof(buf)))
5214 return RETURN_ERR;
5215
5216 return RETURN_OK;
5217}
5218
5219// deletes the mac address from the filter list
5220//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5221INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5222{
5223 char cmd[MAX_CMD_SIZE]={'\0'};
5224 char buf[MAX_BUF_SIZE]={'\0'};
5225
5226#if 0
5227 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5228 if(_syscmd(cmd,buf,sizeof(buf)))
5229 return RETURN_ERR;
5230
5231#endif
5232 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5233 if(_syscmd(cmd,buf,sizeof(buf)))
5234 return RETURN_ERR;
5235
5236 return RETURN_OK;
5237}
5238
5239// outputs the number of devices in the filter list
5240INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5241{
developere6aafda2022-09-13 14:59:28 +08005242 char cmd[MAX_BUF_SIZE]={0};
5243 char buf[MAX_CMD_SIZE]={0};
5244
5245 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5246 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005247 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005248
5249 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5250 _syscmd(cmd, buf, sizeof(buf));
5251
5252 *output_uint = atoi(buf);
5253
5254 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5255 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005256}
5257
5258INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5259{
5260 char cmd[128]={'\0'};
5261 char buf[128]={'\0'};
5262
5263 if(strcmp(action,"DENY")==0)
5264 {
5265 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5266 system(buf);
5267 return RETURN_OK;
5268 }
5269
5270 if(strcmp(action,"ALLOW")==0)
5271 {
5272 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5273 system(buf);
5274 return RETURN_OK;
5275 }
5276
5277 return RETURN_ERR;
5278
5279}
5280
5281// enable kick for devices on acl black list
5282INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5283{
5284 char aclArray[512] = {0}, *acl = NULL;
5285 char assocArray[512] = {0}, *asso = NULL;
5286
developere6aafda2022-09-13 14:59:28 +08005287 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005288 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5289
5290 // if there are no devices connected there is nothing to do
5291 if (strlen(assocArray) < 17)
5292 return RETURN_OK;
5293
5294 if (enable == TRUE)
5295 {
5296 //kick off the MAC which is in ACL array (deny list)
5297 acl = strtok(aclArray, "\r\n");
5298 while (acl != NULL) {
5299 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5300 wifi_kickApAssociatedDevice(apIndex, acl);
5301
5302 acl = strtok(NULL, "\r\n");
5303 }
developere6aafda2022-09-13 14:59:28 +08005304 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005305 }
5306 else
5307 {
developere6aafda2022-09-13 14:59:28 +08005308 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005309 }
5310
5311#if 0
5312 //TODO: need to revisit below implementation
5313 char aclArray[512]={0}, *acl=NULL;
5314 char assocArray[512]={0}, *asso=NULL;
5315 char buf[256]={'\0'};
5316 char action[10]={'\0'};
5317 FILE *fr=NULL;
5318 char interface[10]={'\0'};
5319 char config_file[MAX_BUF_SIZE] = {0};
5320
5321 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5322 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5323 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5324 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5325
5326 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5327 system(buf);
5328 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5329 system(buf);
5330 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5331 system(buf);
5332 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5333 system(buf);
5334 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5335 system(buf);
5336
5337 if ( enable == TRUE )
5338 {
5339 int device_count=0;
5340 strcpy(action,"DENY");
5341 //kick off the MAC which is in ACL array (deny list)
5342 acl = strtok (aclArray,",");
5343 while (acl != NULL) {
5344 if(strlen(acl)>=17)
5345 {
5346 apply_rules(apIndex, acl,action,interface);
5347 device_count++;
5348 //Register mac to be blocked ,in syscfg.db persistent storage
5349 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5350 system(buf);
5351 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5352 system(buf);
5353 system("syscfg commit");
5354
5355 wifi_kickApAssociatedDevice(apIndex, acl);
5356 }
5357 acl = strtok (NULL, ",");
5358 }
5359 }
5360 else
5361 {
5362 int device_count=0;
5363 char cmdmac[20]={'\0'};
5364 strcpy(action,"ALLOW");
5365 //kick off the MAC which is not in ACL array (allow list)
5366 acl = strtok (aclArray,",");
5367 while (acl != NULL) {
5368 if(strlen(acl)>=17)
5369 {
5370 apply_rules(apIndex, acl,action,interface);
5371 device_count++;
5372 //Register mac to be Allowed ,in syscfg.db persistent storage
5373 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5374 system(buf);
5375 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5376 system(buf);
5377 sprintf(cmdmac,"%s",acl);
5378 }
5379 acl = strtok (NULL, ",");
5380 }
5381 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5382 system(buf);
5383
5384 //Disconnect the mac which is not in ACL
5385 asso = strtok (assocArray,",");
5386 while (asso != NULL) {
5387 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5388 wifi_kickApAssociatedDevice(apIndex, asso);
5389 asso = strtok (NULL, ",");
5390 }
5391 }
5392#endif
5393 return RETURN_OK;
5394}
5395
5396INT wifi_setPreferPrivateConnection(BOOL enable)
5397{
5398 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5399 char buf[1024] = {0};
5400
5401 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5402 if(enable == TRUE)
5403 {
5404 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5405 sprintf(buf,"ifconfig %s down" ,interface_name);
5406 system(buf);
5407 memset(buf,0,sizeof(buf));
5408 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5409 sprintf(buf,"ifconfig %s down" ,interface_name);
5410 system(buf);
5411 }
5412 else
5413 {
5414 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5415 if(strcmp(ssid_cur_value,"1") == 0)
5416 wifi_RestartPrivateWifi_5G();
5417 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5418 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5419 if(strcmp(ssid_cur_value,"1") == 0)
5420 wifi_RestartHostapd_2G();
5421 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5422 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5423 if(strcmp(ssid_cur_value,"1") == 0)
5424 wifi_RestartHostapd_5G();
5425 }
5426 return RETURN_OK;
5427}
5428
5429// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5430INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5431{
5432 int items = 1;
5433 struct params list[2];
5434 char buf[MAX_BUF_SIZE] = {0};
5435 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005436 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005437
5438 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005439
developer10adcc12022-09-13 14:39:17 +08005440 if (filterMode == 0) {
5441 sprintf(buf, "%d", 0);
5442 list[0].value = buf;
5443
5444 char cmd[128], rtn[128];
5445 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5446 _syscmd(cmd, rtn, sizeof(rtn));
5447 memset(cmd,0,sizeof(cmd));
5448 // Delete deny_mac_file in hostapd configuration
5449 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5450 _syscmd(cmd, rtn, sizeof(rtn));
5451 }
5452 else if (filterMode == 1) {
5453 sprintf(buf, "%d", filterMode);
5454 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005455 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5456 list[1].name = "accept_mac_file";
5457 list[1].value = acl_file;
5458 items = 2;
developer10adcc12022-09-13 14:39:17 +08005459 } else if (filterMode == 2) {
5460 //TODO: deny_mac_file
5461 sprintf(buf, "%d", 0);
5462 list[0].value = buf;
5463 list[1].name = "deny_mac_file";
5464 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5465 list[1].value = deny_file;
5466 items = 2;
5467 } else {
5468 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005469 }
developer10adcc12022-09-13 14:39:17 +08005470
developer06a01d92022-09-07 16:32:39 +08005471 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5472 wifi_hostapdWrite(config_file, list, items);
5473
5474 return RETURN_OK;
5475
5476#if 0
5477 if(apIndex==0 || apIndex==1)
5478 {
5479 //set the filtermode
5480 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5481 system(buf);
5482 system("syscfg commit");
5483
5484 if(filterMode==0)
5485 {
5486 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5487 system(buf);
5488 return RETURN_OK;
5489 }
5490 }
5491 return RETURN_OK;
5492#endif
5493}
5494
5495// 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.
5496INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5497{
5498 return RETURN_ERR;
5499}
5500
5501// gets the vlan ID for this ap from an internal enviornment variable
5502INT wifi_getApVlanID(INT apIndex, INT *output_int)
5503{
5504 if(apIndex=0)
5505 {
5506 *output_int=100;
5507 return RETURN_OK;
5508 }
5509
5510 return RETURN_ERR;
5511}
5512
5513// sets the vlan ID for this ap to an internal enviornment variable
5514INT wifi_setApVlanID(INT apIndex, INT vlanId)
5515{
5516 //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)
5517 return RETURN_ERR;
5518}
5519
5520// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5521INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5522{
5523 snprintf(bridgeName, 32, "brlan0");
5524 snprintf(IP, 32, "10.0.0.1");
5525 snprintf(subnet, 32, "255.255.255.0");
5526
5527 return RETURN_OK;
5528}
5529
5530//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5531INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5532{
5533 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5534 return RETURN_ERR;
5535}
5536
5537// reset the vlan configuration for this ap
5538INT wifi_resetApVlanCfg(INT apIndex)
5539{
developerf5fef612022-09-20 19:38:26 +08005540 char original_config_file[64] = {0};
5541 char current_config_file[64] = {0};
5542 char buf[64] = {0};
5543 char cmd[64] = {0};
5544 char vlan_file[64] = {0};
5545 char vlan_tagged_interface[16] = {0};
5546 char vlan_bridge[16] = {0};
5547 char vlan_naming[16] = {0};
5548 struct params list[4] = {0};
5549 wifi_band band;
5550
5551 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5552
5553 band = wifi_index_to_band(apIndex);
5554 if (band == band_2_4)
5555 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5556 else if (band = band_5)
5557 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5558 else if (band = band_6)
5559 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5560
5561 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5562
5563 if (strlen(vlan_file) == 0)
5564 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005565
developerf5fef612022-09-20 19:38:26 +08005566 // The file should exist or this vap would not work.
5567 if (access(vlan_file, F_OK) != 0) {
5568 sprintf(cmd, "touch %s", vlan_file);
5569 _syscmd(cmd, buf, sizeof(buf));
5570 }
5571 list[0].name = "vlan_file";
5572 list[0].value = vlan_file;
5573
5574 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5575 list[1].name = "vlan_tagged_interface";
5576 list[1].value = vlan_tagged_interface;
5577
5578 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5579 list[2].name = "vlan_bridge";
5580 list[2].value = vlan_bridge;
5581
5582 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5583 list[3].name = "vlan_naming";
5584 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005585
developerf5fef612022-09-20 19:38:26 +08005586 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5587 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005588 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005589 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005590
developerf5fef612022-09-20 19:38:26 +08005591 // restart this ap
5592 wifi_setApEnable(apIndex, FALSE);
5593 wifi_setApEnable(apIndex, TRUE);
5594
5595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5596
5597 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005598}
5599
5600// 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.
5601INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5602{
5603 return RETURN_ERR;
5604}
5605
5606// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5607INT wifi_startHostApd()
5608{
5609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5610 system("systemctl start hostapd.service");
5611 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5612 return RETURN_OK;
5613 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5614}
5615
5616// stops hostapd
5617INT wifi_stopHostApd()
5618{
5619 char cmd[128] = {0};
5620 char buf[128] = {0};
5621
5622 sprintf(cmd,"systemctl stop hostapd");
5623 _syscmd(cmd, buf, sizeof(buf));
5624
5625 return RETURN_OK;
5626}
5627
5628// restart hostapd dummy function
5629INT wifi_restartHostApd()
5630{
5631 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5632 system("systemctl restart hostapd-global");
5633 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5634
5635 return RETURN_OK;
5636}
5637
5638static int align_hostapd_config(int index)
5639{
5640 ULONG lval;
5641 wifi_getRadioChannel(index%2, &lval);
5642 wifi_setRadioChannel(index%2, lval);
5643}
5644
5645// sets the AP enable status variable for the specified ap.
5646INT wifi_setApEnable(INT apIndex, BOOL enable)
5647{
5648 char config_file[MAX_BUF_SIZE] = {0};
5649 char cmd[MAX_CMD_SIZE] = {0};
5650 char buf[MAX_BUF_SIZE] = {0};
5651 BOOL status;
5652
5653 wifi_getApEnable(apIndex,&status);
5654 if (enable == status)
5655 return RETURN_OK;
5656
5657 if (enable == TRUE) {
5658 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5659 align_hostapd_config(apIndex);
5660 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5661 //Hostapd will bring up this interface
5662 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5663 _syscmd(cmd, buf, sizeof(buf));
5664 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5665 _syscmd(cmd, buf, sizeof(buf));
5666 }
5667 else {
5668 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5669 _syscmd(cmd, buf, sizeof(buf));
5670 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5671 _syscmd(cmd, buf, sizeof(buf));
5672 }
5673 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5674 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5675 _syscmd(cmd, buf, sizeof(buf));
5676 //Wait for wifi up/down to apply
5677 return RETURN_OK;
5678}
5679
5680// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5681INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5682{
5683 char cmd[MAX_CMD_SIZE] = {'\0'};
5684 char buf[MAX_BUF_SIZE] = {'\0'};
5685
5686 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5687 return RETURN_ERR;
5688
5689 *output_bool = 0;
5690
5691 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5692 {
developer70490032022-09-13 15:45:20 +08005693 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005694 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5695 }
5696
5697 return RETURN_OK;
5698}
5699
5700// Outputs the AP "Enabled" "Disabled" status from driver
5701INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5702{
5703 char cmd[128] = {0};
5704 char buf[128] = {0};
5705 BOOL output_bool;
5706
5707 if ( NULL == output_string)
5708 return RETURN_ERR;
5709 wifi_getApEnable(apIndex,&output_bool);
5710
5711 if(output_bool == 1)
5712 snprintf(output_string, 32, "Up");
5713 else
5714 snprintf(output_string, 32, "Disable");
5715
5716 return RETURN_OK;
5717}
5718
5719//Indicates whether or not beacons include the SSID name.
5720// outputs a 1 if SSID on the AP is enabled, else outputs 0
5721INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5722{
5723 //get the running status
5724 char config_file[MAX_BUF_SIZE] = {0};
5725 char buf[16] = {0};
5726
5727 if (!output)
5728 return RETURN_ERR;
5729
5730 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5731 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5732 *output = (strncmp("0",buf,1) == 0);
5733
5734 return RETURN_OK;
5735}
5736
5737// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5738INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5739{
5740 //store the config, apply instantly
5741 char config_file[MAX_BUF_SIZE] = {0};
5742 struct params list;
5743
5744 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5745 list.name = "ignore_broadcast_ssid";
5746 list.value = enable?"0":"1";
5747
5748 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5749 wifi_hostapdWrite(config_file, &list, 1);
5750 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5751 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005752 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005753 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5754
5755 return RETURN_OK;
5756}
5757
5758//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5759INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5760{
5761 //get the running status
5762 if(!output_uint)
5763 return RETURN_ERR;
5764 *output_uint=16;
5765 return RETURN_OK;
5766}
5767
5768INT wifi_setApRetryLimit(INT apIndex, UINT number)
5769{
5770 //apply instantly
5771 return RETURN_ERR;
5772}
5773
5774//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5775INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5776{
5777 if(!output)
5778 return RETURN_ERR;
5779 *output=TRUE;
5780 return RETURN_OK;
5781}
5782
5783//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5784INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5785{
5786 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005787 char cmd[128] = {0};
5788 char buf[128] = {0};
5789 int max_radio_num = 0, radioIndex = 0;
developer3ab38042022-09-13 14:17:03 +08005790
developer0b246d12022-09-30 15:24:20 +08005791 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005792
developer0b246d12022-09-30 15:24:20 +08005793 wifi_getMaxRadioNumber(&max_radio_num);
5794 radioIndex = apIndex % max_radio_num;
5795 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", radioIndex);
5796 _syscmd(cmd,buf, sizeof(buf));
5797
5798 if (strlen(buf) > 0)
5799 *output = true;
5800
5801 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005802
developer06a01d92022-09-07 16:32:39 +08005803 return RETURN_OK;
5804}
5805
5806//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5807INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5808{
5809 //get the running status from driver
5810 if(!output)
5811 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005812
5813 char config_file[MAX_BUF_SIZE] = {0};
5814 char buf[16] = {0};
5815
5816 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5817 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5818 if (strncmp("1",buf,1) == 0)
5819 *output = TRUE;
5820 else
5821 *output = FALSE;
5822
developer06a01d92022-09-07 16:32:39 +08005823 return RETURN_OK;
5824}
5825
5826// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5827INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5828{
5829 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005830 char config_file[MAX_BUF_SIZE] = {0};
5831 struct params list;
5832
5833 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5834 list.name = "wmm_enabled";
5835 list.value = enable?"1":"0";
5836
5837 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5838 wifi_hostapdWrite(config_file, &list, 1);
5839 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5840 wifi_reloadAp(apIndex);
5841 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5842
5843 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005844}
5845
5846//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.
5847INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5848{
5849 //get the running status from driver
5850 if(!output)
5851 return RETURN_ERR;
5852 *output=TRUE;
5853 return RETURN_OK;
5854}
5855
5856// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5857INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5858{
5859 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005860 char config_file[MAX_BUF_SIZE] = {0};
5861 struct params list;
5862
5863 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5864 list.name = "uapsd_advertisement_enabled";
5865 list.value = enable?"1":"0";
5866
5867 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5868 wifi_hostapdWrite(config_file, &list, 1);
5869 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5870 wifi_reloadAp(apIndex);
5871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5872
5873 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005874}
5875
developer6daeb3f2022-09-30 13:36:39 +08005876// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005877INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5878{
developer6daeb3f2022-09-30 13:36:39 +08005879 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5880 char cmd[128] = {0};
5881 char buf[128] = {0};
5882 char ack_filepath[128] = {0};
5883 uint16_t bitmap = 0;
5884 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5885 FILE *f = NULL;
5886
5887 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5888
5889 // Get current setting
5890 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
5891 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
5892 _syscmd(cmd, buf, sizeof(buf));
5893 if (strlen(buf) > 0)
5894 bitmap = strtoul(buf, NULL, 10);
5895
5896 bitmap = strtoul(buf, NULL, 10);
5897
5898 if (ackPolicy == TRUE) { // True, unset this class
5899 bitmap &= ~class_map[class];
5900 } else { // False, set this class
5901 bitmap |= class_map[class];
5902 }
5903
5904 f = fopen(ack_filepath, "w");
5905 if (f == NULL) {
5906 fprintf(stderr, "%s: fopen failed\n", __func__);
5907 return RETURN_ERR;
5908 }
5909 fprintf(f, "%hu", bitmap);
5910 fclose(f);
5911
5912 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
5913 _syscmd(cmd, buf, sizeof(buf));
5914
5915 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5916 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005917}
5918
5919//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.
5920INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5921{
5922 //get the running status from driver
5923 if(!output_uint)
5924 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005925
5926 char output[16]={'\0'};
5927 char config_file[MAX_BUF_SIZE] = {0};
5928
5929 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5930 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5931 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5932 else {
5933 int device_num = atoi(output);
5934 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5935 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5936 return RETURN_ERR;
5937 }
5938 else {
5939 *output_uint = device_num;
5940 }
5941 }
5942
developer06a01d92022-09-07 16:32:39 +08005943 return RETURN_OK;
5944}
5945
5946INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5947{
5948 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005949 char str[MAX_BUF_SIZE]={'\0'};
5950 char cmd[MAX_CMD_SIZE]={'\0'};
5951 struct params params;
5952 char config_file[MAX_BUF_SIZE] = {0};
5953
5954 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5955 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5956 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5957 return RETURN_ERR;
5958 }
5959 sprintf(str, "%d", number);
5960 params.name = "max_num_sta";
5961 params.value = str;
5962
5963 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5964 int ret = wifi_hostapdWrite(config_file, &params, 1);
5965 if (ret) {
5966 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5967 ,__func__, ret);
5968 }
5969
5970 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5971 if (ret) {
5972 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5973 ,__func__, ret);
5974 }
5975 wifi_reloadAp(apIndex);
5976 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5977
5978 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005979}
5980
5981//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.
5982INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5983{
5984 //get the current threshold
5985 if(!output_uint)
5986 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005987 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5988 if (*output_uint == 0)
5989 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08005990 return RETURN_OK;
5991}
5992
5993INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
5994{
5995 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08005996 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
5997 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005998 return RETURN_ERR;
5999}
6000
6001//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.
6002INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6003{
6004 if(!output_uint)
6005 return RETURN_ERR;
6006 *output_uint = 3;
6007 return RETURN_OK;
6008}
6009
6010//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6011INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6012{
6013 if(!output_uint)
6014 return RETURN_ERR;
6015 *output_uint = 3;
6016 return RETURN_OK;
6017}
6018
6019//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.
6020INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6021{
6022 if(!output_in_seconds)
6023 return RETURN_ERR;
6024 *output_in_seconds = 0;
6025 return RETURN_OK;
6026}
6027
6028//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
6029INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6030{
6031 if(!output || apIndex>=MAX_APS)
6032 return RETURN_ERR;
6033 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006034 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006035 return RETURN_OK;
6036}
6037
6038//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6039INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6040{
developer587c1b62022-09-27 15:58:59 +08006041 char config_file[128] = {0};
6042 char wpa[16] = {0};
6043 char key_mgmt[64] = {0};
6044 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006045 if (!output)
6046 return RETURN_ERR;
6047
6048 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006049 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006050
developer587c1b62022-09-27 15:58:59 +08006051 strcpy(output, "None");//Copying "None" to output string for default case
6052 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6053 if (strstr(key_mgmt, "WPA-PSK")) {
6054 if (strcmp(wpa, "1"))
6055 snprintf(output, 32, "WPA-Personal");
6056 else if (strcmp(wpa, "2"))
6057 snprintf(output, 32, "WPA2-Personal");
6058 else if (strcmp(wpa, "3"))
6059 snprintf(output, 32, "WPA-WPA2-Personal");
6060
6061 } else if (strstr(key_mgmt, "WPA-EAP")) {
6062 if (strcmp(wpa, "1"))
6063 snprintf(output, 32, "WPA-Enterprise");
6064 else if (strcmp(wpa, "2"))
6065 snprintf(output, 32, "WPA2-Enterprise");
6066 else if (strcmp(wpa, "3"))
6067 snprintf(output, 32, "WPA-WPA2-Enterprise");
6068 } else if (strstr(key_mgmt, "SAE")) {
6069 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
6070 int disable = strtol(buf, NULL, 16);
6071 if (disable & 0x1)
6072 snprintf(output, 32, "WPA3-Personal");
6073 else
6074 snprintf(output, 32, "WPA3-Transition");
6075 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6076 snprintf(output, 32, "WPA3-Enterprise");
6077 }
developer06a01d92022-09-07 16:32:39 +08006078
6079 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6080 return RETURN_OK;
6081#if 0
6082 //TODO: need to revisit below implementation
6083 char securityType[32], authMode[32];
6084 int enterpriseMode=0;
6085
6086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6087 if(!output)
6088 return RETURN_ERR;
6089
6090 wifi_getApBeaconType(apIndex, securityType);
6091 strcpy(output,"None");//By default, copying "None" to output string
6092 if (strncmp(securityType,"None", strlen("None")) == 0)
6093 return RETURN_OK;
6094
6095 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6096 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6097
6098 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6099 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6100 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6101 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6102 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6103 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6104 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6105
6106 return RETURN_OK;
6107#endif
6108}
6109
6110INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6111{
6112 char securityType[32];
6113 char authMode[32];
6114
6115 //store settings and wait for wifi up to apply
6116 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6117 if(!encMode)
6118 return RETURN_ERR;
6119
developer06a01d92022-09-07 16:32:39 +08006120 if (strcmp(encMode, "None")==0)
6121 {
6122 strcpy(securityType,"None");
6123 strcpy(authMode,"None");
6124 }
6125 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6126 {
6127 strcpy(securityType,"WPAand11i");
6128 strcpy(authMode,"PSKAuthentication");
6129 }
6130 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6131 {
6132 strcpy(securityType,"WPAand11i");
6133 strcpy(authMode,"EAPAuthentication");
6134 }
6135 else if (strcmp(encMode, "WPA-Personal")==0)
6136 {
6137 strcpy(securityType,"WPA");
6138 strcpy(authMode,"PSKAuthentication");
6139 }
6140 else if (strcmp(encMode, "WPA-Enterprise")==0)
6141 {
6142 strcpy(securityType,"WPA");
6143 strcpy(authMode,"EAPAuthentication");
6144 }
6145 else if (strcmp(encMode, "WPA2-Personal")==0)
6146 {
6147 strcpy(securityType,"11i");
6148 strcpy(authMode,"PSKAuthentication");
6149 }
6150 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6151 {
6152 strcpy(securityType,"11i");
6153 strcpy(authMode,"EAPAuthentication");
6154 }
developer587c1b62022-09-27 15:58:59 +08006155 else if (strcmp(encMode, "WPA3-Personal") == 0)
6156 {
6157 strcpy(securityType,"11i");
6158 strcpy(authMode,"SAEAuthentication");
6159 }
6160 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6161 {
6162 strcpy(securityType,"11i");
6163 strcpy(authMode,"EAP_192-bit_Authentication");
6164 }
developer06a01d92022-09-07 16:32:39 +08006165 else
6166 {
6167 strcpy(securityType,"None");
6168 strcpy(authMode,"None");
6169 }
6170 wifi_setApBeaconType(apIndex, securityType);
6171 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6172 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6173
6174 return RETURN_OK;
6175}
6176
6177
6178//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6179// output_string must be pre-allocated as 64 character string by caller
6180// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6181INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6182{
6183 char buf[16];
6184 char config_file[MAX_BUF_SIZE] = {0};
6185
6186 if(output_string==NULL)
6187 return RETURN_ERR;
6188
6189 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6190 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6191
6192 if(strcmp(buf,"0")==0)
6193 {
6194 printf("wpa_mode is %s ......... \n",buf);
6195 return RETURN_ERR;
6196 }
6197
6198 wifi_dbg_printf("\nFunc=%s\n",__func__);
6199 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6200 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6201 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6202
6203 return RETURN_OK;
6204}
6205
6206// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6207// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6208INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6209{
6210 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6211 struct params params={'\0'};
6212 int ret;
6213 char config_file[MAX_BUF_SIZE] = {0};
6214
6215 if(NULL == preSharedKey)
6216 return RETURN_ERR;
6217
6218 params.name = "wpa_passphrase";
6219
6220 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6221 {
6222 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6223 return RETURN_ERR;
6224 }
6225 params.value = preSharedKey;
6226 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6227 ret = wifi_hostapdWrite(config_file, &params, 1);
6228 if(!ret)
6229 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6230 return ret;
6231 //TODO: call hostapd_cli for dynamic_config_control
6232}
6233
6234//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6235// outputs the passphrase, maximum 63 characters
6236INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6237{
6238 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6239
6240 wifi_dbg_printf("\nFunc=%s\n",__func__);
6241 if (NULL == output_string)
6242 return RETURN_ERR;
6243
6244 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6245 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6246 if(strcmp(buf,"0")==0)
6247 {
6248 printf("wpa_mode is %s ......... \n",buf);
6249 return RETURN_ERR;
6250 }
6251
6252 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6253 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6254
6255 return RETURN_OK;
6256}
6257
6258// sets the passphrase enviornment variable, max 63 characters
6259INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6260{
6261 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6262 struct params params={'\0'};
6263 char config_file[MAX_BUF_SIZE] = {0};
6264 int ret;
6265
6266 if(NULL == passPhrase)
6267 return RETURN_ERR;
6268
6269 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6270 {
6271 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6272 return RETURN_ERR;
6273 }
6274 params.name = "wpa_passphrase";
6275 params.value = passPhrase;
6276 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6277 ret=wifi_hostapdWrite(config_file,&params,1);
6278 if(!ret)
6279 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6280
6281 return ret;
6282}
6283
6284//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.
6285INT wifi_setApSecurityReset(INT apIndex)
6286{
developer8d583982022-09-20 11:28:22 +08006287 char original_config_file[64] = {0};
6288 char current_config_file[64] = {0};
6289 char buf[64] = {0};
6290 char cmd[64] = {0};
6291 char wpa[4] = {0};
6292 char wpa_psk[64] = {0};
6293 char wpa_passphrase[64] = {0};
6294 char wpa_psk_file[128] = {0};
6295 char wpa_key_mgmt[64] = {0};
6296 char wpa_pairwise[32] = {0};
6297 wifi_band band;
6298 struct params list[6];
6299
6300 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6301
6302 band = wifi_index_to_band(apIndex);
6303 if (band == band_2_4)
6304 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6305 else if (band = band_5)
6306 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6307 else if (band = band_6)
6308 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6309 else
6310 return RETURN_ERR;
6311
6312 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6313 list[0].name = "wpa";
6314 list[0].value = wpa;
6315
6316 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6317 list[1].name = "wpa_psk";
6318 list[1].value = wpa_psk;
6319
6320 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6321 list[2].name = "wpa_passphrase";
6322 list[2].value = wpa_passphrase;
6323
6324 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6325
6326 if (strlen(wpa_psk_file) == 0)
6327 strcpy(wpa_psk_file, PSK_FILE);
6328
6329 if (access(wpa_psk_file, F_OK) != 0) {
6330 sprintf(cmd, "touch %s", wpa_psk_file);
6331 _syscmd(cmd, buf, sizeof(buf));
6332 }
6333 list[3].name = "wpa_psk_file";
6334 list[3].value = wpa_psk_file;
6335
6336 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6337 list[4].name = "wpa_key_mgmt";
6338 list[4].value = wpa_key_mgmt;
6339
6340 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6341 list[5].name = "wpa_pairwise";
6342 list[5].value = wpa_pairwise;
6343
6344 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6345 wifi_hostapdWrite(current_config_file, list, 6);
6346
6347 wifi_setApEnable(apIndex, FALSE);
6348 wifi_setApEnable(apIndex, TRUE);
6349
6350 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6351 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006352}
6353
6354//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).
6355INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6356{
developer8f2ddd52022-09-13 15:39:24 +08006357 char config_file[64] = {0};
6358 char buf[64] = {0};
6359 char cmd[256] = {0};
6360
6361 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6362
developer06a01d92022-09-07 16:32:39 +08006363 if(!IP_output || !Port_output || !RadiusSecret_output)
6364 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006365
developer8f2ddd52022-09-13 15:39:24 +08006366 // Read the first matched config
6367 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6368 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6369 _syscmd(cmd, buf, sizeof(buf));
6370 strncpy(IP_output, buf, 64);
6371
6372 memset(buf, 0, sizeof(buf));
6373 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6374 _syscmd(cmd, buf, sizeof(buf));
6375 *Port_output = atoi(buf);
6376
6377 memset(buf, 0, sizeof(buf));
6378 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6379 _syscmd(cmd, buf, sizeof(buf));
6380 strncpy(RadiusSecret_output, buf, 64);
6381
6382 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006383 return RETURN_OK;
6384}
6385
6386INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6387{
developer8f2ddd52022-09-13 15:39:24 +08006388 char config_file[64] = {0};
6389 char port_str[8] = {0};
6390 char cmd[256] = {0};
6391 char buf[128] = {0};
6392
6393 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6394
6395 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6396
6397 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6398 _syscmd(cmd, buf, sizeof(buf));
6399 memset(cmd, 0, sizeof(cmd));
6400
6401 snprintf(port_str, sizeof(port_str), "%d", port);
6402 if (strlen(buf) == 0)
6403 // Append
6404 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6405 "auth_server_addr=%s\\n"
6406 "auth_server_port=%s\\n"
6407 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6408 else {
6409 // Delete the three lines setting after the "# radius 1" comment
6410 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6411 _syscmd(cmd, buf, sizeof(buf));
6412 memset(cmd, 0, sizeof(cmd));
6413 // Use "# radius 1" comment to find the location to insert the radius setting
6414 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6415 "# radius 1\\n"
6416 "auth_server_addr=%s\\n"
6417 "auth_server_port=%s\\n"
6418 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6419 }
6420 if(_syscmd(cmd, buf, sizeof(buf))) {
6421 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6422 return RETURN_ERR;
6423 }
6424
6425 wifi_reloadAp(apIndex);
6426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6427 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006428}
6429
6430INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6431{
developer8f2ddd52022-09-13 15:39:24 +08006432 char config_file[64] = {0};
6433 char buf[64] = {0};
6434 char cmd[256] = {0};
6435
6436 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6437
developer06a01d92022-09-07 16:32:39 +08006438 if(!IP_output || !Port_output || !RadiusSecret_output)
6439 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006440
6441 // Read the second matched config
6442 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6443 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6444 _syscmd(cmd, buf, sizeof(buf));
6445 strncpy(IP_output, buf, 64);
6446
6447 memset(buf, 0, sizeof(buf));
6448 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6449 _syscmd(cmd, buf, sizeof(buf));
6450 *Port_output = atoi(buf);
6451
6452 memset(buf, 0, sizeof(buf));
6453 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6454 _syscmd(cmd, buf, sizeof(buf));
6455 strncpy(RadiusSecret_output, buf, 64);
6456
6457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006458 return RETURN_OK;
6459}
6460
6461INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6462{
developer8f2ddd52022-09-13 15:39:24 +08006463 char config_file[64] = {0};
6464 char port_str[8] = {0};
6465 char cmd[256] = {0};
6466 char buf[128] = {0};
6467
6468 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6469
6470 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6471
6472 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6473 _syscmd(cmd, buf, sizeof(buf));
6474 memset(cmd, 0, sizeof(cmd));
6475
6476 snprintf(port_str, sizeof(port_str), "%d", port);
6477 if (strlen(buf) == 0)
6478 // Append
6479 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6480 "auth_server_addr=%s\\n"
6481 "auth_server_port=%s\\n"
6482 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6483 else {
6484 // Delete the three lines setting after the "# radius 2" comment
6485 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6486 _syscmd(cmd, buf, sizeof(buf));
6487 memset(cmd, 0, sizeof(cmd));
6488 // Use "# radius 2" comment to find the location to insert the radius setting
6489 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6490 "# radius 2\\n"
6491 "auth_server_addr=%s\\n"
6492 "auth_server_port=%s\\n"
6493 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6494 }
6495 if(_syscmd(cmd, buf, sizeof(buf))) {
6496 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6497 return RETURN_ERR;
6498 }
6499
6500 wifi_reloadAp(apIndex);
6501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6502 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006503}
6504
6505//RadiusSettings
6506INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6507{
6508 if(!output)
6509 return RETURN_ERR;
6510
6511 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6512 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6513 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6514 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6515 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6516 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.
6517 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6518 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6519 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6520 //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.
6521
6522 return RETURN_OK;
6523}
6524
6525INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6526{
6527 //store the paramters, and apply instantly
6528 return RETURN_ERR;
6529}
6530
6531//Device.WiFi.AccessPoint.{i}.WPS.Enable
6532//Enables or disables WPS functionality for this access point.
6533// outputs the WPS enable state of this ap in output_bool
6534INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6535{
6536 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6537 if(!output_bool || !(apIndex==0 || apIndex==1))
6538 return RETURN_ERR;
6539 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6540 _syscmd(cmd, buf, sizeof(buf));
6541 if(strstr(buf, "configured"))
6542 *output_bool=TRUE;
6543 else
6544 *output_bool=FALSE;
6545
6546 return RETURN_OK;
6547}
6548
6549//Device.WiFi.AccessPoint.{i}.WPS.Enable
6550// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6551INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6552{
6553 char config_file[MAX_BUF_SIZE] = {0};
6554 struct params params;
6555
6556 if(!(apIndex==0 || apIndex==1))
6557 return RETURN_ERR;
6558 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6559 //store the paramters, and wait for wifi up to apply
6560 params.name = "wps_state";
6561 params.value = enable ? "2":"0";
6562
6563 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6564 wifi_hostapdWrite(config_file, &params, 1);
6565 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6566 wifi_reloadAp(apIndex);
6567
6568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6569 return RETURN_OK;
6570}
6571
6572//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
6573INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6574{
6575 if(!output)
6576 return RETURN_ERR;
6577 snprintf(output, 128, "PushButton,PIN");
6578 return RETURN_OK;
6579}
6580
6581//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6582//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.
6583// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6584INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6585{
6586 if(!output)
6587 return RETURN_ERR;
6588 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6589
6590 return RETURN_OK;
6591}
6592
6593//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6594// 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
6595INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6596{
6597 //apply instantly. No setting need to be stored.
6598 char methods[MAX_BUF_SIZE], *token, *next_token;
6599 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6600 struct params params;
6601
6602 if(!methodString || !(apIndex==0 || apIndex==1))
6603 return RETURN_ERR;
6604 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6605 //store the paramters, and wait for wifi up to apply
6606
6607 snprintf(methods, sizeof(methods), "%s", methodString);
6608 for(token=methods; *token; token=next_token)
6609 {
6610 strtok_r(token, ",", &next_token);
6611 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6612 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6613 else if(*token=='E')
6614 {
6615 if(!strcmp(methods, "Ethernet"))
6616 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6617 else if(!strcmp(methods, "ExternalNFCToken"))
6618 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6619 else
6620 printf("%s: Unknown WpsConfigMethod\n", __func__);
6621 }
6622 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6623 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6624 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6625 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6626 else if(*token=='P' )
6627 {
6628 if(!strcmp(token, "PushButton"))
6629 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6630 else if(!strcmp(token, "PIN"))
6631 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6632 else
6633 printf("%s: Unknown WpsConfigMethod\n", __func__);
6634 }
6635 else
6636 printf("%s: Unknown WpsConfigMethod\n", __func__);
6637 }
6638 params.name = "config_methods";
6639 params.value = config_methods;
6640 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6641 wifi_hostapdWrite(config_file, &params, 1);
6642 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6643 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6644
6645 return RETURN_OK;
6646}
6647
6648// outputs the pin value, ulong_pin must be allocated by the caller
6649INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6650{
6651 char buf[MAX_BUF_SIZE] = {0};
6652 char cmd[MAX_CMD_SIZE] = {0};
6653
6654 if(!output_ulong || !(apIndex==0 || apIndex==1))
6655 return RETURN_ERR;
6656 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6657 _syscmd(cmd, buf, sizeof(buf));
6658 if(strlen(buf) > 0)
6659 *output_ulong=strtoul(buf, NULL, 10);
6660
6661 return RETURN_OK;
6662}
6663
6664// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6665INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6666{
6667 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6668 char ap_pin[16] = {0};
6669 char buf[MAX_BUF_SIZE] = {0};
6670 char config_file[MAX_BUF_SIZE] = {0};
6671 ULONG prev_pin = 0;
6672 struct params params;
6673
6674 if(!(apIndex==0 || apIndex==1))
6675 return RETURN_ERR;
6676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6677 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6678 params.name = "ap_pin";
6679 params.value = ap_pin;
6680 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6681 wifi_hostapdWrite(config_file, &params, 1);
6682 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6684
6685 return RETURN_OK;
6686}
6687
6688// Output string is either Not configured or Configured, max 32 characters
6689INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6690{
6691 char cmd[MAX_CMD_SIZE];
6692 char buf[MAX_BUF_SIZE]={0};
6693
6694 if(!output_string || !(apIndex==0 || apIndex==1))
6695 return RETURN_ERR;
6696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6697 snprintf(output_string, 32, "Not configured");
6698 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6699 _syscmd(cmd, buf, sizeof(buf));
6700
developer348e3d92022-09-13 14:48:41 +08006701 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006702 snprintf(output_string, 32, "Configured");
6703 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6704
6705 return RETURN_OK;
6706}
6707
6708// sets the WPS pin for this AP
6709INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6710{
6711 char cmd[MAX_CMD_SIZE];
6712 char buf[MAX_BUF_SIZE]={0};
6713 BOOL enable;
6714
6715 if(!(apIndex==0 || apIndex==1))
6716 return RETURN_ERR;
6717 wifi_getApEnable(apIndex, &enable);
6718 if (!enable)
6719 return RETURN_ERR;
6720 wifi_getApWpsEnable(apIndex, &enable);
6721 if (!enable)
6722 return RETURN_ERR;
6723
6724 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6725 _syscmd(cmd, buf, sizeof(buf));
6726 if((strstr(buf, "OK"))!=NULL)
6727 return RETURN_OK;
6728
6729 return RETURN_ERR;
6730}
6731
6732// This function is called when the WPS push button has been pressed for this AP
6733INT wifi_setApWpsButtonPush(INT apIndex)
6734{
6735 char cmd[MAX_CMD_SIZE];
6736 char buf[MAX_BUF_SIZE]={0};
6737 BOOL enable=FALSE;
6738
6739 if(!(apIndex==0 || apIndex==1))
6740 return RETURN_ERR;
6741 wifi_getApEnable(apIndex, &enable);
6742 if (!enable)
6743 return RETURN_ERR;
6744
6745 wifi_getApWpsEnable(apIndex, &enable);
6746 if (!enable)
6747 return RETURN_ERR;
6748
6749 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6750 _syscmd(cmd, buf, sizeof(buf));
6751
6752 if((strstr(buf, "OK"))!=NULL)
6753 return RETURN_OK;
6754 return RETURN_ERR;
6755}
6756
6757// cancels WPS mode for this AP
6758INT wifi_cancelApWPS(INT apIndex)
6759{
6760 char cmd[MAX_CMD_SIZE];
6761 char buf[MAX_BUF_SIZE]={0};
6762
6763 if(!(apIndex==0 || apIndex==1))
6764 return RETURN_ERR;
6765 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6766 _syscmd(cmd,buf, sizeof(buf));
6767
6768 if((strstr(buf, "OK"))!=NULL)
6769 return RETURN_OK;
6770 return RETURN_ERR;
6771}
6772
6773//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6774//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6775INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6776{
6777 FILE *f;
6778 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6779 char cmd[256], buf[2048];
6780 char *param , *value, *line=NULL;
6781 size_t len = 0;
6782 ssize_t nread;
6783 wifi_associated_dev_t *dev=NULL;
6784
6785 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6786 *associated_dev_array = NULL;
6787 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6788 _syscmd(cmd,buf,sizeof(buf));
6789 *output_array_size = atoi(buf);
6790
6791 if (*output_array_size <= 0)
6792 return RETURN_OK;
6793
6794 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6795 *associated_dev_array = dev;
6796 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6797 _syscmd(cmd,buf,sizeof(buf));
6798 f = fopen("/tmp/connected_devices.txt", "r");
6799 if (f==NULL)
6800 {
6801 *output_array_size=0;
6802 return RETURN_ERR;
6803 }
6804 while ((nread = getline(&line, &len, f)) != -1)
6805 {
6806 param = strtok(line,"=");
6807 value = strtok(NULL,"=");
6808
6809 if( strcmp("flags",param) == 0 )
6810 {
6811 value[strlen(value)-1]='\0';
6812 if(strstr (value,"AUTHORIZED") != NULL )
6813 {
6814 dev[auth_temp].cli_AuthenticationState = 1;
6815 dev[auth_temp].cli_Active = 1;
6816 auth_temp++;
6817 read_flag=1;
6818 }
6819 }
6820 if(read_flag==1)
6821 {
6822 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6823 {
6824 value[strlen(value)-1]='\0';
6825 sscanf(value, "%x:%x:%x:%x:%x:%x",
6826 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6827 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6828 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6829 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6830 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6831 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6832 mac_temp++;
6833 read_flag=0;
6834 }
6835 }
6836 }
6837 *output_array_size = auth_temp;
6838 auth_temp=0;
6839 mac_temp=0;
6840 free(line);
6841 fclose(f);
6842 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6843 return RETURN_OK;
6844}
6845
6846#define MACADDRESS_SIZE 6
6847
6848INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6849{
6850 FILE *fp = NULL;
6851 char str[MAX_BUF_SIZE] = {0};
6852 int wificlientindex = 0 ;
6853 int count = 0;
6854 int signalstrength = 0;
6855 int arr[MACADDRESS_SIZE] = {0};
6856 unsigned char mac[MACADDRESS_SIZE] = {0};
6857 UINT wifi_count = 0;
6858 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6859 char pipeCmd[MAX_CMD_SIZE] = {0};
6860
6861 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6862 *output_array_size = 0;
6863 *associated_dev_array = NULL;
6864
6865 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6866 fp = popen(pipeCmd, "r");
6867 if (fp == NULL)
6868 {
6869 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6870 return RETURN_ERR;
6871 }
6872
6873 /* Read the output a line at a time - output it. */
6874 fgets(str, sizeof(str)-1, fp);
6875 wifi_count = (unsigned int) atoi ( str );
6876 *output_array_size = wifi_count;
6877 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6878 pclose(fp);
6879
6880 if(wifi_count == 0)
6881 {
6882 return RETURN_OK;
6883 }
6884 else
6885 {
6886 wifi_associated_dev3_t* temp = NULL;
6887 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6888 if(temp == NULL)
6889 {
6890 printf("Error Statement. Insufficient memory \n");
6891 return RETURN_ERR;
6892 }
6893
6894 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6895 system(pipeCmd);
6896 memset(pipeCmd,0,sizeof(pipeCmd));
6897 if(apIndex == 0)
6898 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6899 else if(apIndex == 1)
6900 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6901 system(pipeCmd);
6902
6903 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6904 if(fp == NULL)
6905 {
6906 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6907 return RETURN_ERR;
6908 }
6909 fclose(fp);
6910
6911 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6912 fp = popen(pipeCmd, "r");
6913 if(fp)
6914 {
6915 for(count =0 ; count < wifi_count; count++)
6916 {
6917 fgets(str, MAX_BUF_SIZE, fp);
6918 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6919 {
6920 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6921 {
6922 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6923
6924 }
6925 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6926 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]);
6927 }
6928 temp[count].cli_AuthenticationState = 1; //TODO
6929 temp[count].cli_Active = 1; //TODO
6930 }
6931 pclose(fp);
6932 }
6933
6934 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6935 fp = popen(pipeCmd, "r");
6936 if(fp)
6937 {
6938 pclose(fp);
6939 }
6940 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6941 if(fp)
6942 {
6943 for(count =0 ; count < wifi_count ;count++)
6944 {
6945 fgets(str, MAX_BUF_SIZE, fp);
6946 signalstrength = atoi(str);
6947 temp[count].cli_SignalStrength = signalstrength;
6948 temp[count].cli_RSSI = signalstrength;
6949 temp[count].cli_SNR = signalstrength + 95;
6950 }
6951 pclose(fp);
6952 }
6953
6954
6955 if((apIndex == 0) || (apIndex == 4))
6956 {
6957 for(count =0 ; count < wifi_count ;count++)
6958 {
6959 strcpy(temp[count].cli_OperatingStandard,"g");
6960 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6961 }
6962
6963 //BytesSent
6964 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6965 fp = popen(pipeCmd, "r");
6966 if(fp)
6967 {
6968 pclose(fp);
6969 }
6970 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6971 if(fp)
6972 {
6973 for (count = 0; count < wifi_count; count++)
6974 {
6975 fgets(str, MAX_BUF_SIZE, fp);
6976 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6977 }
6978 pclose(fp);
6979 }
6980
6981 //BytesReceived
6982 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6983 fp = popen(pipeCmd, "r");
6984 if (fp)
6985 {
6986 pclose(fp);
6987 }
6988 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6989 if (fp)
6990 {
6991 for (count = 0; count < wifi_count; count++)
6992 {
6993 fgets(str, MAX_BUF_SIZE, fp);
6994 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
6995 }
6996 pclose(fp);
6997 }
6998
6999 //PacketsSent
7000 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7001 fp = popen(pipeCmd, "r");
7002 if (fp)
7003 {
7004 pclose(fp);
7005 }
7006
7007 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7008 if (fp)
7009 {
7010 for (count = 0; count < wifi_count; count++)
7011 {
7012 fgets(str, MAX_BUF_SIZE, fp);
7013 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7014 }
7015 pclose(fp);
7016 }
7017
7018 //PacketsReceived
7019 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7020 fp = popen(pipeCmd, "r");
7021 if (fp)
7022 {
7023 pclose(fp);
7024 }
7025 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7026 if (fp)
7027 {
7028 for (count = 0; count < wifi_count; count++)
7029 {
7030 fgets(str, MAX_BUF_SIZE, fp);
7031 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7032 }
7033 pclose(fp);
7034 }
7035
7036 //ErrorsSent
7037 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7038 fp = popen(pipeCmd, "r");
7039 if (fp)
7040 {
7041 pclose(fp);
7042 }
7043 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7044 if (fp)
7045 {
7046 for (count = 0; count < wifi_count; count++)
7047 {
7048 fgets(str, MAX_BUF_SIZE, fp);
7049 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7050 }
7051 pclose(fp);
7052 }
7053
7054 //ErrorsSent
7055 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7056 fp = popen(pipeCmd, "r");
7057 if (fp)
7058 {
7059 pclose(fp);
7060 }
7061 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7062 if (fp)
7063 {
7064 for (count = 0; count < wifi_count; count++)
7065 {
7066 fgets(str, MAX_BUF_SIZE, fp);
7067 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7068 }
7069 pclose(fp);
7070 }
7071
7072 //LastDataDownlinkRate
7073 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7074 fp = popen(pipeCmd, "r");
7075 if (fp)
7076 {
7077 pclose(fp);
7078 }
7079 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7080 if (fp)
7081 {
7082 for (count = 0; count < wifi_count; count++)
7083 {
7084 fgets(str, MAX_BUF_SIZE, fp);
7085 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7086 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7087 }
7088 pclose(fp);
7089 }
7090
7091 //LastDataUplinkRate
7092 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7093 fp = popen(pipeCmd, "r");
7094 if (fp)
7095 {
7096 pclose(fp);
7097 }
7098 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7099 if (fp)
7100 {
7101 for (count = 0; count < wifi_count; count++)
7102 {
7103 fgets(str, MAX_BUF_SIZE, fp);
7104 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7105 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7106 }
7107 pclose(fp);
7108 }
7109
7110 }
7111 else if ((apIndex == 1) || (apIndex == 5))
7112 {
7113 for (count = 0; count < wifi_count; count++)
7114 {
7115 strcpy(temp[count].cli_OperatingStandard, "a");
7116 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7117 temp[count].cli_BytesSent = 0;
7118 temp[count].cli_BytesReceived = 0;
7119 temp[count].cli_LastDataUplinkRate = 0;
7120 temp[count].cli_LastDataDownlinkRate = 0;
7121 temp[count].cli_PacketsSent = 0;
7122 temp[count].cli_PacketsReceived = 0;
7123 temp[count].cli_ErrorsSent = 0;
7124 }
7125 }
7126
7127 for (count = 0; count < wifi_count; count++)
7128 {
7129 temp[count].cli_Retransmissions = 0;
7130 temp[count].cli_DataFramesSentAck = 0;
7131 temp[count].cli_DataFramesSentNoAck = 0;
7132 temp[count].cli_MinRSSI = 0;
7133 temp[count].cli_MaxRSSI = 0;
7134 strncpy(temp[count].cli_InterferenceSources, "", 64);
7135 memset(temp[count].cli_IPAddress, 0, 64);
7136 temp[count].cli_RetransCount = 0;
7137 temp[count].cli_FailedRetransCount = 0;
7138 temp[count].cli_RetryCount = 0;
7139 temp[count].cli_MultipleRetryCount = 0;
7140 }
7141 *associated_dev_array = temp;
7142 }
7143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7144 return RETURN_OK;
7145}
7146
7147int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7148{
7149 FILE *fp = NULL;
7150 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7151 char cmd[MAX_CMD_SIZE];
7152 int count = 0;
7153
7154 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7155 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7156 fp = popen(cmd,"r");
7157 if(fp == NULL)
7158 {
7159 printf("Failed to run command in Function %s\n",__FUNCTION__);
7160 return 0;
7161 }
7162 if(fgets(path, sizeof(path)-1, fp) != NULL)
7163 {
7164 for(count=0;path[count]!='\n';count++)
7165 status[count]=path[count];
7166 status[count]='\0';
7167 }
7168 strcpy(wifi_status,status);
7169 pclose(fp);
7170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7171 return RETURN_OK;
7172}
7173
7174/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7175struct hostapd_sta_param {
7176 char key[50];
7177 char value[100];
7178}
7179
7180static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7181 int i = 0;
7182
7183 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7184 if (strncmp(params[i].key,key,50) == 0){
7185 return &params[i].value;
7186 }
7187 i++;
7188 }
7189 return NULL;
7190
7191} */
7192
7193static unsigned int count_occurences(const char *buf, const char *word)
7194{
7195 unsigned int n = 0;
7196 char *ptr = strstr(buf, word);
7197
7198 while (ptr++) {
7199 n++;
7200 ptr = strstr(ptr, word);
7201 }
7202
7203 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7204 return n;
7205}
7206
7207static const char *get_line_from_str_buf(const char *buf, char *line)
7208{
7209 int i;
7210 int n = strlen(buf);
7211
7212 for (i = 0; i < n; i++) {
7213 line[i] = buf[i];
7214 if (buf[i] == '\n') {
7215 line[i] = '\0';
7216 return &buf[i + 1];
7217 }
7218 }
7219
7220 return NULL;
7221}
7222
7223INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7224{
7225 unsigned int assoc_cnt = 0;
7226 char interface_name[50] = {0};
7227 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7228 char cmd[MAX_CMD_SIZE] = {'\0'};
7229 char line[256] = {'\0'};
7230 int i = 0;
7231 int ret = 0;
7232 const char *ptr = NULL;
7233 char *key = NULL;
7234 char *val = NULL;
7235 wifi_associated_dev3_t *temp = NULL;
7236 int rssi;
7237
7238 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7239
7240 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7241 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7242 return RETURN_ERR;
7243 }
7244
7245 // Example filtered output of 'iw dev' command:
7246 // Station 0a:69:72:10:d2:fa (on wifi0)
7247 // signal avg:-67 [-71, -71] dBm
7248 // Station 28:c2:1f:25:5f:99 (on wifi0)
7249 // signal avg:-67 [-71, -70] dBm
7250 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7251 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7252 return RETURN_ERR;
7253 }
7254
7255 ret = _syscmd(cmd, buf, sizeof(buf));
7256 if (ret == RETURN_ERR) {
7257 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7258 return RETURN_ERR;
7259 }
7260
7261 *output_array_size = count_occurences(buf, "Station");
7262 if (*output_array_size == 0) return RETURN_OK;
7263
7264 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7265 if (temp == NULL) {
7266 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7267 return RETURN_ERR;
7268 }
7269 *associated_dev_array = temp;
7270
7271 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7272 ptr = get_line_from_str_buf(buf, line);
7273 i = -1;
7274 while (ptr) {
7275 if (strstr(line, "Station")) {
7276 i++;
7277 key = strtok(line, " ");
7278 val = strtok(NULL, " ");
7279 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7280 &temp[i].cli_MACAddress[0],
7281 &temp[i].cli_MACAddress[1],
7282 &temp[i].cli_MACAddress[2],
7283 &temp[i].cli_MACAddress[3],
7284 &temp[i].cli_MACAddress[4],
7285 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7286 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7287 free(*associated_dev_array);
7288 return RETURN_ERR;
7289 }
7290 }
7291 else if (i < 0) {
7292 ptr = get_line_from_str_buf(ptr, line);
7293 continue; // We didn't detect 'station' entry yet
7294 }
7295 else if (strstr(line, "signal avg")) {
7296 key = strtok(line, ":");
7297 val = strtok(NULL, " ");
7298 if (sscanf(val, "%d", &rssi) <= 0 ) {
7299 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7300 free(*associated_dev_array);
7301 return RETURN_ERR;
7302 }
7303 temp[i].cli_RSSI = rssi;
7304 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7305 }
7306 // Here other fields can be parsed if added to filter of 'iw dev' command
7307
7308 ptr = get_line_from_str_buf(ptr, line);
7309 };
7310
7311 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7312
7313 return RETURN_OK;
7314}
7315
7316#if 0
7317//To-do
7318INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7319{
7320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7321
7322 //Using different approach to get required WiFi Parameters from system available commands
7323#if 0
7324 FILE *f;
7325 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7326 char cmd[256], buf[2048];
7327 char *param , *value, *line=NULL;
7328 size_t len = 0;
7329 ssize_t nread;
7330 wifi_associated_dev3_t *dev=NULL;
7331 *associated_dev_array = NULL;
7332 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7333 _syscmd(cmd,buf,sizeof(buf));
7334 *output_array_size = atoi(buf);
7335
7336 if (*output_array_size <= 0)
7337 return RETURN_OK;
7338
7339 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7340 *associated_dev_array = dev;
7341 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7342 _syscmd(cmd,buf,sizeof(buf));
7343 f = fopen("/tmp/connected_devices.txt", "r");
7344 if (f==NULL)
7345 {
7346 *output_array_size=0;
7347 return RETURN_ERR;
7348 }
7349 while ((nread = getline(&line, &len, f)) != -1)
7350 {
7351 param = strtok(line,"=");
7352 value = strtok(NULL,"=");
7353
7354 if( strcmp("flags",param) == 0 )
7355 {
7356 value[strlen(value)-1]='\0';
7357 if(strstr (value,"AUTHORIZED") != NULL )
7358 {
7359 dev[auth_temp].cli_AuthenticationState = 1;
7360 dev[auth_temp].cli_Active = 1;
7361 auth_temp++;
7362 read_flag=1;
7363 }
7364 }
7365 if(read_flag==1)
7366 {
7367 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7368 {
7369 value[strlen(value)-1]='\0';
7370 sscanf(value, "%x:%x:%x:%x:%x:%x",
7371 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7372 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7373 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7374 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7375 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7376 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7377
7378 }
7379 else if( strcmp("rx_packets",param) == 0 )
7380 {
7381 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7382 }
7383
7384 else if( strcmp("tx_packets",param) == 0 )
7385 {
7386 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7387 }
7388
7389 else if( strcmp("rx_bytes",param) == 0 )
7390 {
7391 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7392 }
7393
7394 else if( strcmp("tx_bytes",param) == 0 )
7395 {
7396 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7397 mac_temp++;
7398 read_flag=0;
7399 }
7400 }
7401 }
7402
7403 *output_array_size = auth_temp;
7404 auth_temp=0;
7405 mac_temp=0;
7406 free(line);
7407 fclose(f);
7408#endif
7409 char interface_name[MAX_BUF_SIZE] = {0};
7410 char wifi_status[MAX_BUF_SIZE] = {0};
7411 char hostapdconf[MAX_BUF_SIZE] = {0};
7412
7413 wifi_associated_dev3_t *dev_array = NULL;
7414 ULONG wifi_count = 0;
7415
7416 *associated_dev_array = NULL;
7417 *output_array_size = 0;
7418
7419 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7420 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7421 {
7422 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7423
7424 GetInterfaceName(interface_name, hostapdconf);
7425
7426 if(strlen(interface_name) > 1)
7427 {
7428 wifihal_interfacestatus(wifi_status,interface_name);
7429 if(strcmp(wifi_status,"RUNNING") == 0)
7430 {
7431 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7432
7433 *associated_dev_array = dev_array;
7434 *output_array_size = wifi_count;
7435 }
7436 else
7437 {
7438 *associated_dev_array = NULL;
7439 }
7440 }
7441 }
7442
7443 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7444 return RETURN_OK;
7445}
7446#endif
7447
7448/* getIPAddress function */
7449/**
7450* @description Returning IpAddress of the Matched String
7451*
7452* @param
7453* @str Having MacAddress
7454* @ipaddr Having ipaddr
7455* @return The status of the operation
7456* @retval RETURN_OK if successful
7457* @retval RETURN_ERR if any error is detected
7458*
7459*/
7460
7461INT getIPAddress(char *str,char *ipaddr)
7462{
7463 FILE *fp = NULL;
7464 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7465 int LeaseTime = 0,ret = 0;
7466 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7467 {
7468 return RETURN_ERR;
7469 }
7470
7471 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7472 {
7473 /*
7474 Sample:sss
7475 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7476 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7477 */
7478 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7479 &(LeaseTime),
7480 phyAddr,
7481 ipAddr,
7482 hostName
7483 );
7484 if(ret != 4)
7485 continue;
7486 if(strcmp(str,phyAddr) == 0)
7487 strcpy(ipaddr,ipAddr);
7488 }
7489 return RETURN_OK;
7490}
7491
7492/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7493/**
7494* @description Returning Inactive wireless connected clients informations
7495*
7496* @param
7497* @filename Holding private_wifi 2g/5g content files
7498* @associated_dev_array Having inactiv wireless clients informations
7499* @output_array_size Returning Inactive wireless counts
7500* @return The status of the operation
7501* @retval RETURN_OK if successful
7502* @retval RETURN_ERR if any error is detected
7503*
7504*/
7505
7506INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7507{
7508 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7509 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7510 FILE *fp = NULL;
7511 int arr[MACADDRESS_SIZE] = {0};
7512 unsigned char mac[MACADDRESS_SIZE] = {0};
7513 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7514 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7515 fp = popen(buf,"r");
7516 if(fp == NULL)
7517 return RETURN_ERR;
7518 else
7519 {
7520 fgets(path,sizeof(path),fp);
7521 maccount = atoi(path);
7522 }
7523 pclose(fp);
7524 *output_array_size = maccount;
7525 wifi_associated_dev3_t* temp = NULL;
7526 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7527 *associated_dev_array = temp;
7528 if(temp == NULL)
7529 {
7530 printf("Error Statement. Insufficient memory \n");
7531 return RETURN_ERR;
7532 }
7533 memset(buf,0,sizeof(buf));
7534 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7535 fp = popen(buf,"r");
7536 for(count = 0; count < maccount ; count++)
7537 {
7538 fgets(path,sizeof(path),fp);
7539 for(i = 0; path[i]!='\n';i++)
7540 str[i]=path[i];
7541 str[i]='\0';
7542 getIPAddress(str,ipaddr);
7543 memset(buf,0,sizeof(buf));
7544 if(strlen(ipaddr) > 0)
7545 {
7546 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7547 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7548 {
7549 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7550 {
7551 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7552 {
7553 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7554
7555 }
7556 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7557 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]);
7558 }
7559 temp[count].cli_AuthenticationState = 0; //TODO
7560 temp[count].cli_Active = 0; //TODO
7561 temp[count].cli_SignalStrength = 0;
7562 }
7563 else //Active wireless clients info
7564 {
7565 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7566 {
7567 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7568 {
7569 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7570
7571 }
7572 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7573 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]);
7574 }
7575 temp[count].cli_Active = 1;
7576 }
7577 }
7578 memset(ipaddr,0,sizeof(ipaddr));
7579 }
7580 pclose(fp);
7581 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7582 return RETURN_OK;
7583}
7584//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7585//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7586//To get Band Steering Capability
7587INT wifi_getBandSteeringCapability(BOOL *support)
7588{
7589 *support = FALSE;
7590 return RETURN_OK;
7591}
7592
7593
7594//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7595//To get Band Steering enable status
7596INT wifi_getBandSteeringEnable(BOOL *enable)
7597{
7598 *enable = FALSE;
7599 return RETURN_OK;
7600}
7601
7602//To turn on/off Band steering
7603INT wifi_setBandSteeringEnable(BOOL enable)
7604{
7605 return RETURN_OK;
7606}
7607
7608//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7609//To get Band Steering AP group
7610INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7611{
7612 if (NULL == output_ApGroup)
7613 return RETURN_ERR;
7614
7615 strcpy(output_ApGroup, "1,2");
7616 return RETURN_OK;
7617}
7618
7619//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7620//to set and read the band steering BandUtilizationThreshold parameters
7621INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7622{
7623 return RETURN_ERR;
7624}
7625
7626INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7627{
7628 return RETURN_ERR;
7629}
7630
7631//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7632//to set and read the band steering RSSIThreshold parameters
7633INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7634{
7635 return RETURN_ERR;
7636}
7637
7638INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7639{
7640 return RETURN_ERR;
7641}
7642
7643
7644//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7645//to set and read the band steering physical modulation rate threshold parameters
7646INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7647{
7648 //If chip is not support, return -1
7649 return RETURN_ERR;
7650}
7651
7652INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7653{
7654 //If chip is not support, return -1
7655 return RETURN_ERR;
7656}
7657
7658//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7659//to set and read the inactivity time (in seconds) for steering under overload condition
7660INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7661{
7662 return RETURN_ERR;
7663}
7664
7665INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7666{
7667 return RETURN_ERR;
7668}
7669
7670//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7671//to set and read the inactivity time (in seconds) for steering under Idle condition
7672INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7673{
7674 return RETURN_ERR;
7675}
7676
7677INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7678{
7679 return RETURN_ERR;
7680}
7681
7682//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7683//pClientMAC[64]
7684//pSourceSSIDIndex[64]
7685//pDestSSIDIndex[64]
7686//pSteeringReason[256]
7687INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7688{
7689 //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
7690 *pSteeringTime=time(NULL);
7691 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7692 return RETURN_OK;
7693}
7694
7695INT wifi_ifConfigDown(INT apIndex)
7696{
7697 INT status = RETURN_OK;
7698 char cmd[64];
7699
7700 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7701 printf("%s: %s\n", __func__, cmd);
7702 system(cmd);
7703
7704 return status;
7705}
7706
7707INT wifi_ifConfigUp(INT apIndex)
7708{
7709 char cmd[128];
7710 char buf[1024];
7711
7712 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7713 _syscmd(cmd, buf, sizeof(buf));
7714 return 0;
7715}
7716
7717//>> Deprecated. Replace with wifi_applyRadioSettings
7718INT wifi_pushBridgeInfo(INT apIndex)
7719{
7720 char ip[32];
7721 char subnet[32];
7722 char bridge[32];
7723 int vlanId;
7724 char cmd[128];
7725 char buf[1024];
7726
7727 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7728 wifi_getApVlanID(apIndex,&vlanId);
7729
7730 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7731 _syscmd(cmd,buf, sizeof(buf));
7732
7733 return 0;
7734}
7735
7736INT wifi_pushChannel(INT radioIndex, UINT channel)
7737{
7738 char cmd[128];
7739 char buf[1024];
7740 int apIndex;
7741
7742 apIndex=(radioIndex==0)?0:1;
7743 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7744 _syscmd(cmd,buf, sizeof(buf));
7745
7746 return 0;
7747}
7748
7749INT wifi_pushChannelMode(INT radioIndex)
7750{
7751 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7752 return RETURN_ERR;
7753}
7754
7755INT wifi_pushDefaultValues(INT radioIndex)
7756{
7757 //Apply Comcast specified default radio settings instantly
7758 //AMPDU=1
7759 //AMPDUFrames=32
7760 //AMPDULim=50000
7761 //txqueuelen=1000
7762
7763 return RETURN_ERR;
7764}
7765
7766INT wifi_pushTxChainMask(INT radioIndex)
7767{
7768 //Apply default TxChainMask instantly
7769 return RETURN_ERR;
7770}
7771
7772INT wifi_pushRxChainMask(INT radioIndex)
7773{
7774 //Apply default RxChainMask instantly
7775 return RETURN_ERR;
7776}
7777
7778INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7779{
7780 INT status;
7781
7782 status = wifi_setSSIDName(apIndex,ssid);
7783 wifi_setApEnable(apIndex,FALSE);
7784 wifi_setApEnable(apIndex,TRUE);
7785
7786 return status;
7787}
7788
7789INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7790{
7791 //Apply default Ssid Advertisement instantly
7792 return RETURN_ERR;
7793}
7794
7795INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7796{
7797 INT status = RETURN_ERR;
7798 *output = 0;
7799 return RETURN_ERR;
7800}
7801
7802INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7803{
7804 return RETURN_OK;
7805}
7806
7807INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7808{
7809 return RETURN_OK;
7810}
7811
7812//To-do
7813INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7814{
developereb199ae2022-09-13 14:04:27 +08007815 char output[16]={'\0'};
7816 char config_file[MAX_BUF_SIZE] = {0};
7817
7818 if (!output_string)
7819 return RETURN_ERR;
7820
7821 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7822 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7823
7824 if (strlen(output) == 0)
7825 snprintf(output_string, 64, "Disabled");
7826 else if (strncmp(output, "0", 1) == 0)
7827 snprintf(output_string, 64, "Disabled");
7828 else if (strncmp(output, "1", 1) == 0)
7829 snprintf(output_string, 64, "Optional");
7830 else if (strncmp(output, "2", 1) == 0)
7831 snprintf(output_string, 64, "Required");
7832 else {
7833 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7834 return RETURN_ERR;
7835 }
7836
7837 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007838 return RETURN_OK;
7839}
7840INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7841{
developereb199ae2022-09-13 14:04:27 +08007842 char str[MAX_BUF_SIZE]={'\0'};
7843 char cmd[MAX_CMD_SIZE]={'\0'};
7844 struct params params;
7845 char config_file[MAX_BUF_SIZE] = {0};
7846
7847 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7848 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7849 return RETURN_ERR;
7850
7851 params.name = "ieee80211w";
7852 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7853 params.value = "0";
7854 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7855 params.value = "1";
7856 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7857 params.value = "2";
7858 else{
7859 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7860 return RETURN_ERR;
7861 }
7862 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7863 wifi_hostapdWrite(config_file, &params, 1);
7864 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007865 return RETURN_OK;
7866}
7867INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7868{
7869 char output[16]={'\0'};
7870 char config_file[MAX_BUF_SIZE] = {0};
7871
7872 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7873 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7874 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7875
7876 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7877 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7878
7879 return RETURN_OK;
7880}
7881
7882INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7883{
7884 return RETURN_OK;
7885}
7886
7887INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7888{
7889 return RETURN_OK;
7890}
7891
7892INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7893{
7894 return RETURN_OK;
7895}
7896
7897INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7898{
7899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7900 char config_file[MAX_BUF_SIZE] = {0};
7901
7902 if (NULL == output)
7903 return RETURN_ERR;
7904 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7905 wifi_hostapdRead(config_file,"hw_mode",output,64);
7906
7907 if(strcmp(output,"b")==0)
7908 sprintf(output, "%s", "1,2,5.5,11");
7909 else if (strcmp(output,"a")==0)
7910 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7911 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7912 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7913
7914 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7915 return RETURN_OK;
7916}
7917
7918INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7919{
7920 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7921 char *temp;
7922 char temp_output[128];
7923 char temp_TransmitRates[128];
7924 char config_file[MAX_BUF_SIZE] = {0};
7925
7926 if (NULL == output)
7927 return RETURN_ERR;
7928
7929 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7930 wifi_hostapdRead(config_file,"supported_rates",output,64);
7931
7932 strcpy(temp_TransmitRates,output);
7933 strcpy(temp_output,"");
7934 temp = strtok(temp_TransmitRates," ");
7935 while(temp!=NULL)
7936 {
7937 temp[strlen(temp)-1]=0;
7938 if((temp[0]=='5') && (temp[1]=='\0'))
7939 {
7940 temp="5.5";
7941 }
7942 strcat(temp_output,temp);
7943 temp = strtok(NULL," ");
7944 if(temp!=NULL)
7945 {
7946 strcat(temp_output,",");
7947 }
7948 }
7949 strcpy(output,temp_output);
7950 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7951
7952 return RETURN_OK;
7953}
7954
7955INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7956{
7957 return RETURN_OK;
7958}
7959
7960
7961INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7962{
7963 int i=0;
7964 char *temp;
7965 char temp1[128];
7966 char temp_output[128];
7967 char temp_TransmitRates[128];
7968 struct params params={'\0'};
7969 char config_file[MAX_BUF_SIZE] = {0};
7970
7971 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7972 if(NULL == output)
7973 return RETURN_ERR;
7974
7975 strcpy(temp_TransmitRates,output);
7976
7977 for(i=0;i<strlen(temp_TransmitRates);i++)
7978 {
7979 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7980 {
7981 continue;
7982 }
7983 else
7984 {
7985 return RETURN_ERR;
7986 }
7987 }
7988 strcpy(temp_output,"");
7989 temp = strtok(temp_TransmitRates," ");
7990 while(temp!=NULL)
7991 {
7992 strcpy(temp1,temp);
7993 if(wlanIndex==1)
7994 {
7995 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
7996 {
7997 return RETURN_ERR;
7998 }
7999 }
8000
8001 if(strcmp(temp,"5.5")==0)
8002 {
8003 strcpy(temp1,"55");
8004 }
8005 else
8006 {
8007 strcat(temp1,"0");
8008 }
8009 strcat(temp_output,temp1);
8010 temp = strtok(NULL," ");
8011 if(temp!=NULL)
8012 {
8013 strcat(temp_output," ");
8014 }
8015 }
8016 strcpy(output,temp_output);
8017
8018
8019 params.name = "supported_rates";
8020 params.value = output;
8021
8022 wifi_dbg_printf("\n%s:",__func__);
8023 wifi_dbg_printf("params.value=%s\n",params.value);
8024 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8025 wifi_hostapdWrite(config_file,&params,1);
8026 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8027
8028 return RETURN_OK;
8029}
8030
8031
8032static char *sncopy(char *dst, int dst_sz, const char *src)
8033{
8034 if (src && dst && dst_sz > 0) {
8035 strncpy(dst, src, dst_sz);
8036 dst[dst_sz - 1] = '\0';
8037 }
8038 return dst;
8039}
8040
8041static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8042{
8043 if (0 == strcmp(ht_mode, "HT40") ||
8044 0 == strcmp(ht_mode, "HT80") ||
8045 0 == strcmp(ht_mode, "HT160")) {
8046 switch (channel) {
8047 case 1 ... 7:
8048 case 36:
8049 case 44:
8050 case 52:
8051 case 60:
8052 case 100:
8053 case 108:
8054 case 116:
8055 case 124:
8056 case 132:
8057 case 140:
8058 case 149:
8059 case 157:
8060 return 1;
8061 case 8 ... 13:
8062 case 40:
8063 case 48:
8064 case 56:
8065 case 64:
8066 case 104:
8067 case 112:
8068 case 120:
8069 case 128:
8070 case 136:
8071 case 144:
8072 case 153:
8073 case 161:
8074 return -1;
8075 default:
8076 return -EINVAL;
8077 }
8078 }
8079
8080 return -EINVAL;
8081}
8082
8083static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8084{
8085 if (NULL == hw_mode) return;
8086
8087 if (0 == strcmp(hw_mode, "ac"))
8088 sncopy(bw_mode, bw_mode_len, "ht vht");
8089
8090 if (0 == strcmp(hw_mode, "n"))
8091 sncopy(bw_mode, bw_mode_len, "ht");
8092
8093 return;
8094}
8095
8096static int util_chan_to_freq(int chan)
8097{
8098 if (chan == 14)
8099 return 2484;
8100 else if (chan < 14)
8101 return 2407 + chan * 5;
8102 else if (chan >= 182 && chan <= 196)
8103 return 4000 + chan * 5;
8104 else
8105 return 5000 + chan * 5;
8106 return 0;
8107}
8108
8109const int *util_unii_5g_chan2list(int chan, int width)
8110{
8111 static const int lists[] = {
8112 // <width>, <chan1>, <chan2>..., 0,
8113 20, 36, 0,
8114 20, 40, 0,
8115 20, 44, 0,
8116 20, 48, 0,
8117 20, 52, 0,
8118 20, 56, 0,
8119 20, 60, 0,
8120 20, 64, 0,
8121 20, 100, 0,
8122 20, 104, 0,
8123 20, 108, 0,
8124 20, 112, 0,
8125 20, 116, 0,
8126 20, 120, 0,
8127 20, 124, 0,
8128 20, 128, 0,
8129 20, 132, 0,
8130 20, 136, 0,
8131 20, 140, 0,
8132 20, 144, 0,
8133 20, 149, 0,
8134 20, 153, 0,
8135 20, 157, 0,
8136 20, 161, 0,
8137 20, 165, 0,
8138 40, 36, 40, 0,
8139 40, 44, 48, 0,
8140 40, 52, 56, 0,
8141 40, 60, 64, 0,
8142 40, 100, 104, 0,
8143 40, 108, 112, 0,
8144 40, 116, 120, 0,
8145 40, 124, 128, 0,
8146 40, 132, 136, 0,
8147 40, 140, 144, 0,
8148 40, 149, 153, 0,
8149 40, 157, 161, 0,
8150 80, 36, 40, 44, 48, 0,
8151 80, 52, 56, 60, 64, 0,
8152 80, 100, 104, 108, 112, 0,
8153 80, 116, 120, 124, 128, 0,
8154 80, 132, 136, 140, 144, 0,
8155 80, 149, 153, 157, 161, 0,
8156 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8157 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8158 -1 // final delimiter
8159 };
8160 const int *start;
8161 const int *p;
8162
8163 for (p = lists; *p != -1; p++) {
8164 if (*p == width) {
8165 for (start = ++p; *p != 0; p++) {
8166 if (*p == chan)
8167 return start;
8168 }
8169 }
8170 // move to the end of channel list of given width
8171 while (*p != 0) {
8172 p++;
8173 }
8174 }
8175
8176 return NULL;
8177}
8178
8179static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8180{
8181 if (NULL == ht_mode)
8182 return 0;
8183
8184 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8185 const int *chans = util_unii_5g_chan2list(channel, width);
8186 int sum = 0;
8187 int cnt = 0;
8188
8189 if (NULL == chans)
8190 return 0;
8191
8192 while (*chans) {
8193 sum += *chans;
8194 cnt++;
8195 chans++;
8196 }
8197 return sum / cnt;
8198}
8199
8200static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8201{
8202 BOOL onlyG, onlyN, onlyA;
8203 CHAR tmp[64];
8204 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8205 if (ret == RETURN_OK) {
8206 sncopy(hw_mode, hw_mode_size, tmp);
8207 }
8208 return ret;
8209}
8210
8211INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8212{
8213 // Sample commands:
8214 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8215 // hostapd_cli -i wifi0 chan_switch 30 2437
8216 char cmd[MAX_CMD_SIZE] = {0};
8217 char buf[MAX_BUF_SIZE] = {0};
8218 int freq = 0, ret = 0;
8219 char center_freq1_str[32] = ""; // center_freq1=%d
8220 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8221 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8222 char hw_mode[16] = ""; // n|ac
8223 char bw_mode[16] = ""; // ht|ht vht
8224 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8225 int sec_chan_offset;
8226 int width;
8227
8228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8229
8230 freq = util_chan_to_freq(channel);
8231
8232 // Get radio mode HT20|HT40|HT80 etc.
8233 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
8234 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8235 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8236 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8237 if (sec_chan_offset != -EINVAL)
8238 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
8239
8240
8241 // Provide bandwith if specified
8242 if (channel_width_MHz > 20) {
8243 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8244 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8245 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
8246
8247 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8248 }
8249
8250 int center_chan = 0;
8251 if (channel_width_MHz > 20) {
8252 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8253 if (center_chan > 0) {
8254 int center_freq1 = util_chan_to_freq(center_chan);
8255 if (center_freq1)
8256 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8257 }
8258 }
8259
8260 {
8261 // Only the first AP, other are hanging on the same radio
8262 int apIndex = radioIndex;
8263 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8264 AP_PREFIX, apIndex, csa_beacon_count, freq,
8265 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8266 wifi_dbg_printf("execute: '%s'\n", cmd);
8267 ret = _syscmd(cmd, buf, sizeof(buf));
8268 }
8269
8270 wifi_setRadioChannel(radioIndex, channel);
8271
8272 char *ext_str = "None";
8273 if (sec_chan_offset == 1) ext_str = "Above";
8274 else if (sec_chan_offset == -1) ext_str = "Below";
8275 wifi_setRadioExtChannel(radioIndex, ext_str);
8276
8277 wifi_setRadioCenterChannel(radioIndex, center_chan);
8278
8279 char mhz_str[16];
8280 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8281 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8282
8283 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8284
8285 return RETURN_OK;
8286}
8287
8288INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8289{
developer615510b2022-09-27 10:14:35 +08008290 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008291 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008292 char cmd[256]={0};
8293 char buf[128]={0};
8294 char file_name[32] = {0};
8295 char filter_SSID[32] = {0};
8296 char line[256] = {0};
8297 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008298 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008299 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008300 size_t len=0;
8301 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008302 int vht_channel_width = 0;
developer615510b2022-09-27 10:14:35 +08008303 bool get_nosie_ret = false;
8304 bool filter_enable = false;
8305 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008306
developer615510b2022-09-27 10:14:35 +08008307 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008308
developer615510b2022-09-27 10:14:35 +08008309 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8310 f = fopen(file_name, "r");
8311 if (f != NULL) {
8312 fgets(filter_SSID, sizeof(file_name), f);
8313 if (strlen(filter_SSID) != 0)
8314 filter_enable = true;
8315 fclose(f);
8316 }
8317
8318 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8319 _syscmd(cmd, buf, sizeof(buf));
8320 channels_num = strtol(buf, NULL, 10);
8321
8322 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8323 get_nosie_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8324
8325 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8326 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radio_index, AP_PREFIX, radio_index);
8327 fprintf(stderr, "cmd: %s\n", cmd);
8328 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008329 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8330 return RETURN_ERR;
8331 }
developer615510b2022-09-27 10:14:35 +08008332 ret = fgets(line, sizeof(line), f);
8333 while (ret != NULL) {
8334 if(strstr(line, "BSS") != NULL) { // new neighbor info
8335 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8336 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8337 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8338
8339 if (!filter_BSS) {
8340 index++;
8341 wifi_neighbor_ap2_t *tmp;
8342 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8343 if (tmp == NULL) { // no more memory to use
8344 index--;
8345 wifi_dbg_printf("%s: realloc failed\n", __func__);
8346 break;
8347 }
8348 scan_array = tmp;
8349 }
8350 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008351
developer615510b2022-09-27 10:14:35 +08008352 filter_BSS = false;
8353 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8354 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8355 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8356 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8357 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008358 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008359 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008360
developer615510b2022-09-27 10:14:35 +08008361 if (freq >= 2412 && freq <= 2484) {
8362 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8363 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8364 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8365 }
8366 else if (freq >= 5160 && freq <= 5805) {
8367 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8368 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8369 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8370 }
developer06a01d92022-09-07 16:32:39 +08008371
developer615510b2022-09-27 10:14:35 +08008372 scan_array[index].ap_Noise = 0;
8373 if (get_nosie_ret) {
8374 for (int i = 0; i < channels_num; i++) {
8375 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8376 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8377 break;
8378 }
8379 }
developer06a01d92022-09-07 16:32:39 +08008380 }
developer615510b2022-09-27 10:14:35 +08008381 } else if (strstr(line, "beacon interval") != NULL) {
8382 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8383 } else if (strstr(line, "signal") != NULL) {
8384 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8385 } else if (strstr(line,"SSID") != NULL) {
8386 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8387 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8388 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008389 }
developer615510b2022-09-27 10:14:35 +08008390 } else if (strstr(line, "Supported rates") != NULL) {
8391 char SRate[80] = {0}, *tmp = NULL;
8392 memset(buf, 0, sizeof(buf));
8393 strcpy(SRate, line);
8394 tmp = strtok(SRate, ":");
8395 tmp = strtok(NULL, ":");
8396 strcpy(buf, tmp);
8397 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008398
developer615510b2022-09-27 10:14:35 +08008399 tmp = strtok(buf, " \n");
8400 while (tmp != NULL) {
8401 strcat(SRate, tmp);
8402 if (SRate[strlen(SRate) - 1] == '*') {
8403 SRate[strlen(SRate) - 1] = '\0';
8404 }
8405 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008406
developer615510b2022-09-27 10:14:35 +08008407 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008408 }
developer615510b2022-09-27 10:14:35 +08008409 SRate[strlen(SRate) - 1] = '\0';
8410 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8411 } else if (strstr(line, "DTIM") != NULL) {
8412 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8413 } else if (strstr(line, "VHT capabilities") != NULL) {
8414 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8415 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8416 } else if (strstr(line, "HT capabilities") != NULL) {
8417 strcat(scan_array[index].ap_SupportedStandards, ",n");
8418 strcpy(scan_array[index].ap_OperatingStandards, "n");
8419 } else if (strstr(line, "VHT operation") != NULL) {
8420 ret = fgets(line, sizeof(line), f);
8421 sscanf(line," * channel width: %d", &vht_channel_width);
8422 if(vht_channel_width == 1) {
8423 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8424 } else {
8425 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8426 }
8427 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8428 continue;
8429 } else if (strstr(line, "HT operation") != NULL) {
8430 ret = fgets(line, sizeof(line), f);
8431 sscanf(line," * secondary channel offset: %s", &buf);
8432 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008433 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008434 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
developer06a01d92022-09-07 16:32:39 +08008435 }
developer615510b2022-09-27 10:14:35 +08008436 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008437 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008438 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8439 } else {
8440 //20Mhz
8441 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
developer06a01d92022-09-07 16:32:39 +08008442 }
developer615510b2022-09-27 10:14:35 +08008443 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008444 continue;
developer615510b2022-09-27 10:14:35 +08008445 } else if (strstr(line, "HE capabilities") != NULL) {
8446 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8447 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8448 ret = fgets(line, sizeof(line), f);
8449 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8450 if (strstr(line, "HE40/2.4GHz") != NULL)
8451 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8452 else
8453 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8454 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8455 if (strstr(line, "HE80/5GHz") != NULL) {
8456 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8457 ret = fgets(line, sizeof(line), f);
8458 } else
8459 continue;
8460 if (strstr(line, "HE160/5GHz") != NULL)
8461 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008462 }
developer615510b2022-09-27 10:14:35 +08008463 continue;
8464 } else if (strstr(line, "WPA") != NULL) {
8465 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8466 } else if (strstr(line, "RSN") != NULL) {
8467 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8468 } else if (strstr(line, "Group cipher") != NULL) {
8469 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8470 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8471 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008472 }
developer06a01d92022-09-07 16:32:39 +08008473 }
developer615510b2022-09-27 10:14:35 +08008474 ret = fgets(line, sizeof(line), f);
8475 }
8476
8477 if (!filter_BSS) {
8478 *output_array_size = index + 1;
8479 } else {
8480 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8481 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008482 }
developer06a01d92022-09-07 16:32:39 +08008483 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008484 pclose(f);
developer615510b2022-09-27 10:14:35 +08008485 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008486 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008487}
developer615510b2022-09-27 10:14:35 +08008488
developer06a01d92022-09-07 16:32:39 +08008489INT wifi_getApAssociatedDeviceStats(
8490 INT apIndex,
8491 mac_address_t *clientMacAddress,
8492 wifi_associated_dev_stats_t *associated_dev_stats,
8493 u64 *handle)
8494{
8495 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8496 char interface_name[50] = {0};
8497 char cmd[1024] = {0};
8498 char mac_str[18] = {0};
8499 char *key = NULL;
8500 char *val = NULL;
8501 FILE *f = NULL;
8502 char *line = NULL;
8503 size_t len = 0;
8504 ssize_t read = 0;
8505
8506 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8507 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8508 return RETURN_ERR;
8509 }
8510
8511 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8512 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8513 if((f = popen(cmd, "r")) == NULL) {
8514 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8515 return RETURN_ERR;
8516 }
8517
8518 while ((read = getline(&line, &len, f)) != -1) {
8519 key = strtok(line,":");
8520 val = strtok(NULL,":");
8521
8522 if(!strncmp(key,"rx bytes",8))
8523 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8524 if(!strncmp(key,"tx bytes",8))
8525 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8526 if(!strncmp(key,"rx packets",10))
8527 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8528 if(!strncmp(key,"tx packets",10))
8529 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8530 if(!strncmp(key,"tx retries",10))
8531 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8532 if(!strncmp(key,"tx failed",9))
8533 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8534 if(!strncmp(key,"rx drop misc",13))
8535 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8536 if(!strncmp(key,"rx bitrate",10)) {
8537 val = strtok(val, " ");
8538 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8539 }
8540 if(!strncmp(key,"tx bitrate",10)) {
8541 val = strtok(val, " ");
8542 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8543 }
8544 }
8545 free(line);
8546 pclose(f);
8547 return RETURN_OK;
8548}
8549
8550INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8551{
8552 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8553
8554 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8555 if (NULL == output_string)
8556 return RETURN_ERR;
8557
8558 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8559 _syscmd(cmd, buf, sizeof(buf));
8560
8561 //size of SSID name restricted to value less than 32 bytes
8562 snprintf(output_string, 32, "%s", buf);
8563 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8564
8565 return RETURN_OK;
8566}
8567
8568INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8569{
8570 //char cmd[MAX_CMD_SIZE] = {0};
8571 char config_file[MAX_BUF_SIZE] = {0};
8572 char buf[32] = {0};
8573
8574 if (!output_filterMode)
8575 return RETURN_ERR;
8576
8577 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8578 //_syscmd(cmd, buf, sizeof(buf));
8579 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8580 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008581 if(strlen(buf) == 0) {
8582 *output_filterMode = 0;
8583 }
8584 else {
8585 int macaddr_acl_mode = strtol(buf, NULL, 10);
8586 if (macaddr_acl_mode == 1) {
8587 *output_filterMode = 1;
8588 } else if (macaddr_acl_mode == 0) {
8589 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8590 if (strlen(buf) == 0) {
8591 *output_filterMode = 0;
8592 } else {
8593 *output_filterMode = 2;
8594 }
8595 } else {
8596 return RETURN_ERR;
8597 }
8598 }
developer06a01d92022-09-07 16:32:39 +08008599
8600 return RETURN_OK;
8601}
8602
8603INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8604{
8605 FILE *fp = NULL;
8606 char str[MAX_BUF_SIZE] = {0};
8607 int wificlientindex = 0 ;
8608 int count = 0;
8609 int signalstrength = 0;
8610 int arr[MACADDRESS_SIZE] = {0};
8611 unsigned char mac[MACADDRESS_SIZE] = {0};
8612 UINT wifi_count = 0;
8613 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8614 char pipeCmd[MAX_CMD_SIZE] = {0};
8615
8616 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8617 *output_array_size = 0;
8618 *associated_dev_array = NULL;
8619 char interface_name[50] = {0};
8620
8621 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8622 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8623 return RETURN_ERR;
8624 }
8625
8626 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8627 fp = popen(pipeCmd, "r");
8628 if (fp == NULL)
8629 {
8630 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8631 return RETURN_ERR;
8632 }
8633
8634 /* Read the output a line at a time - output it. */
8635 fgets(str, sizeof(str)-1, fp);
8636 wifi_count = (unsigned int) atoi ( str );
8637 *output_array_size = wifi_count;
8638 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8639 pclose(fp);
8640
8641 if(wifi_count == 0)
8642 {
8643 return RETURN_OK;
8644 }
8645 else
8646 {
8647 wifi_associated_dev2_t* temp = NULL;
8648 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8649 *associated_dev_array = temp;
8650 if(temp == NULL)
8651 {
8652 printf("Error Statement. Insufficient memory \n");
8653 return RETURN_ERR;
8654 }
8655
8656 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8657 system(pipeCmd);
8658
8659 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8660 if(fp == NULL)
8661 {
8662 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8663 return RETURN_ERR;
8664 }
8665 fclose(fp);
8666
8667 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8668 fp = popen(pipeCmd, "r");
8669 if(fp)
8670 {
8671 for(count =0 ; count < wifi_count; count++)
8672 {
8673 fgets(str, MAX_BUF_SIZE, fp);
8674 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8675 {
8676 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8677 {
8678 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8679
8680 }
8681 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8682 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]);
8683 }
8684 temp[count].cli_AuthenticationState = 1; //TODO
8685 temp[count].cli_Active = 1; //TODO
8686 }
8687 pclose(fp);
8688 }
8689
8690 //Updating RSSI per client
8691 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8692 fp = popen(pipeCmd, "r");
8693 if(fp)
8694 {
8695 pclose(fp);
8696 }
8697 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8698 if(fp)
8699 {
8700 for(count =0 ; count < wifi_count ;count++)
8701 {
8702 fgets(str, MAX_BUF_SIZE, fp);
8703 signalstrength = atoi(str);
8704 temp[count].cli_RSSI = signalstrength;
8705 }
8706 pclose(fp);
8707 }
8708
8709
8710 //LastDataDownlinkRate
8711 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8712 fp = popen(pipeCmd, "r");
8713 if (fp)
8714 {
8715 pclose(fp);
8716 }
8717 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8718 if (fp)
8719 {
8720 for (count = 0; count < wifi_count; count++)
8721 {
8722 fgets(str, MAX_BUF_SIZE, fp);
8723 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8724 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8725 }
8726 pclose(fp);
8727 }
8728
8729 //LastDataUplinkRate
8730 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8731 fp = popen(pipeCmd, "r");
8732 if (fp)
8733 {
8734 pclose(fp);
8735 }
8736 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8737 if (fp)
8738 {
8739 for (count = 0; count < wifi_count; count++)
8740 {
8741 fgets(str, MAX_BUF_SIZE, fp);
8742 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8743 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8744 }
8745 pclose(fp);
8746 }
8747 }
8748 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8749 return RETURN_OK;
8750
8751}
8752
8753INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8754{
8755#if 0
8756 /*char buf[1024] = {0};
8757 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8758 _syscmd(cmd, buf, sizeof(buf));*/
8759
8760 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8761 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8762 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8763 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8764
8765 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.
8766 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].
8767 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].
8768 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].
8769 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8770 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8771
8772 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8773 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8774 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8775 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.
8776 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.
8777 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.
8778 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.
8779 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.
8780 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.
8781 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.
8782 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8783#endif
8784
8785 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008786 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008787 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008788 char pipeCmd[128] = {0};
8789 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008790 wifi_ssidTrafficStats2_t *out = output_struct;
8791
developerce736392022-09-13 15:24:34 +08008792 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008793 if (!output_struct)
8794 return RETURN_ERR;
8795
developerce736392022-09-13 15:24:34 +08008796 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8797 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8798 GetInterfaceName(interface_name, HConf_file);
8799 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008800
developer06a01d92022-09-07 16:32:39 +08008801 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008802 if (fp == NULL) {
8803 fprintf(stderr, "%s: popen failed\n", __func__);
8804 return RETURN_ERR;
8805 }
8806 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008807
developerce736392022-09-13 15:24:34 +08008808 if (strlen(str) == 0) // interface not exist
8809 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008810
developerce736392022-09-13 15:24:34 +08008811 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8812 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008813 pclose(fp);
8814
developerce736392022-09-13 15:24:34 +08008815 memset(str, 0, sizeof(str));
8816 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008817 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008818 if (fp == NULL) {
8819 fprintf(stderr, "%s: popen failed\n", __func__);
8820 return RETURN_ERR;
8821 }
8822 fgets(str, sizeof(str), fp);
8823
8824 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8825 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008826 pclose(fp);
developerce736392022-09-13 15:24:34 +08008827
8828 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8829 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8830
8831 // Not supported
8832 output_struct->ssid_RetransCount = 0;
8833 output_struct->ssid_FailedRetransCount = 0;
8834 output_struct->ssid_RetryCount = 0;
8835 output_struct->ssid_MultipleRetryCount = 0;
8836 output_struct->ssid_ACKFailureCount = 0;
8837 output_struct->ssid_AggregatedPacketCount = 0;
8838
developer06a01d92022-09-07 16:32:39 +08008839 return RETURN_OK;
8840}
8841
8842//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).
8843INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8844{
8845 char output_val[16]={'\0'};
8846 char config_file[MAX_BUF_SIZE] = {0};
8847
8848 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8849 if (!output)
8850 return RETURN_ERR;
8851 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8852 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8853
8854 if( strcmp(output_val,"1") == 0 )
8855 *output = TRUE;
8856 else
8857 *output = FALSE;
8858 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8859
8860 return RETURN_OK;
8861}
8862
8863INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8864{
8865 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8866 char str[MAX_BUF_SIZE]={'\0'};
8867 char string[MAX_BUF_SIZE]={'\0'};
8868 char cmd[MAX_CMD_SIZE]={'\0'};
8869 char *ch;
8870 char config_file[MAX_BUF_SIZE] = {0};
8871 struct params params;
8872
8873 if(enable == TRUE)
8874 strcpy(string,"1");
8875 else
8876 strcpy(string,"0");
8877
8878 params.name = "ap_isolate";
8879 params.value = string;
8880
8881 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8882 wifi_hostapdWrite(config_file,&params,1);
8883 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8884
8885 return RETURN_OK;
8886}
8887
8888INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8889{
8890 if (NULL == output_dBm)
8891 return RETURN_ERR;
8892
8893 *output_dBm = 0;
8894 return RETURN_OK;
8895}
8896
8897INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8898{
8899 return RETURN_OK;
8900}
8901INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8902{
8903 return RETURN_OK;
8904}
8905INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8906{
8907 return RETURN_OK;
8908}
8909INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8910{
8911 return RETURN_OK;
8912}
8913INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8914{
8915 return RETURN_OK;
8916}
8917INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8918{
8919 char config_file[MAX_BUF_SIZE] = {0};
8920 struct params list;
8921
8922 list.name = "bss_transition";
8923 list.value = activate?"1":"0";
8924 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8925 wifi_hostapdWrite(config_file, &list, 1);
8926
8927 return RETURN_OK;
8928}
8929wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8930
8931void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8932{
8933 return;
8934}
8935
8936INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8937{
8938 // TODO Implement me!
8939 return RETURN_OK;
8940}
8941
8942INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8943{
developera3c68b92022-09-13 15:27:29 +08008944 char file_name[128] = {0};
8945 char buf[128] = {0};
8946 FILE *f = NULL;
8947
8948 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8949
8950 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8951 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8952 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8953 f = fopen(file_name, "w");
8954 if (f == NULL)
8955 return RETURN_ERR;
8956 // For mode == 0 is to disable filter, just don't write to the file.
8957 if (mode)
8958 fprintf(f, "%s", essid);
8959
8960 fclose(f);
8961 }
8962 } else { // special case, need to set AP's SSID as filter for each radio.
8963 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8964 f = fopen(file_name, "w");
8965 if (f == NULL)
8966 return RETURN_ERR;
8967
8968 // For mode == 0 is to disable filter, just don't write to the file.
8969 if (mode)
8970 fprintf(f, "%s", essid);
8971
8972 fclose(f);
8973 }
8974
8975 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008976 return RETURN_OK;
8977}
8978
8979INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
8980{
8981 // TODO Implement me!
8982 //Apply wifi_pushRadioChannel() instantly
8983 return RETURN_ERR;
8984}
8985
8986INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
8987{
8988 // TODO Implement me!
8989 return RETURN_OK;
8990}
8991
8992#ifdef HAL_NETLINK_IMPL
8993static int tidStats_callback(struct nl_msg *msg, void *arg) {
8994 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8995 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8996 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8997 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
8998 int rem , tid_index = 0;
8999
9000 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9001 wifi_associated_dev_tid_entry_t *stats_entry;
9002
9003 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9004 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9005 };
9006 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9007 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9008 };
9009
9010 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9011 genlmsg_attrlen(gnlh, 0), NULL);
9012
9013
9014 if (!tb[NL80211_ATTR_STA_INFO]) {
9015 fprintf(stderr, "station stats missing!\n");
9016 return NL_SKIP;
9017 }
9018
9019 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9020 tb[NL80211_ATTR_STA_INFO],
9021 stats_policy)) {
9022 fprintf(stderr, "failed to parse nested attributes!\n");
9023 return NL_SKIP;
9024 }
9025
9026 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9027 {
9028 stats_entry = &out->tid_array[tid_index];
9029
9030 stats_entry->tid = tid_index;
9031 stats_entry->ac = _tid_ac_index_get[tid_index];
9032
9033 if(sinfo[NL80211_STA_INFO_TID_STATS])
9034 {
9035 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9036 printf("failed to parse nested stats attributes!");
9037 return NL_SKIP;
9038 }
9039 }
9040 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9041 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9042
9043 if(tid_index < (PS_MAX_TID - 1))
9044 tid_index++;
9045 }
9046 //ToDo: sum_time_ms, ewma_time_ms
9047 return NL_SKIP;
9048}
9049#endif
9050
9051INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9052{
9053#ifdef HAL_NETLINK_IMPL
9054 Netlink nl;
9055 char if_name[10];
9056
9057 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9058
9059 nl.id = initSock80211(&nl);
9060
9061 if (nl.id < 0) {
9062 fprintf(stderr, "Error initializing netlink \n");
9063 return -1;
9064 }
9065
9066 struct nl_msg* msg = nlmsg_alloc();
9067
9068 if (!msg) {
9069 fprintf(stderr, "Failed to allocate netlink message.\n");
9070 nlfree(&nl);
9071 return -2;
9072 }
9073
9074 genlmsg_put(msg,
9075 NL_AUTO_PORT,
9076 NL_AUTO_SEQ,
9077 nl.id,
9078 0,
9079 0,
9080 NL80211_CMD_GET_STATION,
9081 0);
9082
9083 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9084 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9085 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9086 nl_send_auto(nl.socket, msg);
9087 nl_recvmsgs(nl.socket, nl.cb);
9088 nlmsg_free(msg);
9089 nlfree(&nl);
9090 return RETURN_OK;
9091#else
9092//iw implementation
9093#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9094#define TOTAL_MAX_LINES 50
9095
9096 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9097 char if_name[10];
9098 FILE *fp=NULL;
9099 char pipeCmd[1024]= {'\0'};
9100 int lines,tid_index=0;
9101 char mac_addr[20] = {'\0'};
9102
9103 wifi_associated_dev_tid_entry_t *stats_entry;
9104
9105 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9106 strcpy(mac_addr,clientMacAddress);
9107
9108 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9109 fp= popen(pipeCmd,"r");
9110 if(fp == NULL)
9111 {
9112 perror("popen for station dump failed\n");
9113 return RETURN_ERR;
9114 }
9115 pclose(fp);
9116
9117 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9118 fp=popen(pipeCmd,"r");
9119 if(fp == NULL)
9120 {
9121 perror("popen for grep station failed\n");
9122 return RETURN_ERR;
9123 }
9124 else if(fgets(buf,sizeof(buf),fp) != NULL)
9125 lines=atoi(buf);
9126 else
9127 {
9128 pclose(fp);
9129 fprintf(stderr,"No devices are connected \n");
9130 return RETURN_ERR;
9131 }
9132 pclose(fp);
9133
9134 if(lines == 1)
9135 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9136
9137 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9138 {
9139 stats_entry = &tid_stats->tid_array[tid_index];
9140 stats_entry->tid = tid_index;
9141
9142 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);
9143
9144 fp=popen(pipeCmd,"r");
9145 if(fp ==NULL)
9146 {
9147 perror("Failed to read from tid file \n");
9148 return RETURN_ERR;
9149 }
9150 else if(fgets(buf,sizeof(buf),fp) != NULL)
9151 stats_entry->num_msdus = atol(buf);
9152
9153 pclose(fp);
9154 stats_entry->ac = _tid_ac_index_get[tid_index];
9155// TODO:
9156// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9157// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9158 }
9159 return RETURN_OK;
9160#endif
9161}
9162
9163
9164INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9165{
developer615510b2022-09-27 10:14:35 +08009166 char cmd[128]={0};
9167 char buf[128]={0};
9168 int freq = 0;
9169
9170 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9171
9172 // full mode is used to scan all channels.
9173 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9174 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9175 ieee80211_channel_to_frequency(chan_list[0], &freq);
9176
9177 if (freq)
9178 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9179 else
9180 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9181
9182 _syscmd(cmd, buf, sizeof(buf));
9183 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9184
developer06a01d92022-09-07 16:32:39 +08009185 return RETURN_OK;
9186}
9187
9188
9189INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9190{
9191 // TODO Implement me!
9192 return RETURN_ERR;
9193}
9194
9195INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9196{
9197 // TODO Implement me!
9198 return RETURN_ERR;
9199}
9200
9201INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9202{
9203 // TODO Implement me!
9204 return RETURN_ERR;
9205}
9206
9207INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9208{
9209 // TODO Implement me!
9210 return RETURN_ERR;
9211}
9212
9213INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9214{
9215 // TODO Implement me!
9216 return RETURN_ERR;
9217}
9218
9219INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9220{
9221 // TODO Implement me!
9222 return RETURN_ERR;
9223}
9224
9225INT wifi_steering_eventUnregister(void)
9226{
9227 // TODO Implement me!
9228 return RETURN_ERR;
9229}
9230
9231INT wifi_delApAclDevices(INT apIndex)
9232{
9233#if 0
9234 char cmd[MAX_BUF_SIZE] = {0};
9235 char buf[MAX_BUF_SIZE] = {0};
9236
9237 /* Not reset proof solution */
9238 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9239 if(_syscmd(cmd,buf,sizeof(buf)))
9240 return RETURN_ERR;
9241#endif
developere6aafda2022-09-13 14:59:28 +08009242 char cmd[MAX_CMD_SIZE]={0};
9243 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009244
developere6aafda2022-09-13 14:59:28 +08009245 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9246 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9247 if(_syscmd(cmd, buf, sizeof(buf)))
9248 return RETURN_ERR;
9249 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009250
9251 return RETURN_OK;
9252}
9253
9254#ifdef HAL_NETLINK_IMPL
9255static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9256 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9257 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9258 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9259 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9260 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9261 char mac_addr[20],dev[20];
9262
9263 nla_parse(tb,
9264 NL80211_ATTR_MAX,
9265 genlmsg_attrdata(gnlh, 0),
9266 genlmsg_attrlen(gnlh, 0),
9267 NULL);
9268
9269 if(!tb[NL80211_ATTR_STA_INFO]) {
9270 fprintf(stderr, "sta stats missing!\n");
9271 return NL_SKIP;
9272 }
9273
9274 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9275 fprintf(stderr, "failed to parse nested attributes!\n");
9276 return NL_SKIP;
9277 }
9278 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9279
9280 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9281
9282 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9283 fprintf(stderr, "failed to parse nested rate attributes!");
9284 return NL_SKIP;
9285 }
9286
9287 if(sinfo[NL80211_STA_INFO_TID_STATS])
9288 {
9289 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9290 printf("failed to parse nested stats attributes!");
9291 return NL_SKIP;
9292 }
9293 }
9294
9295 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9296 {
9297 printf("Type is VHT\n");
9298 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9299 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9300
9301 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9302 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9303 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9304 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9305 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9306 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9307 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9308 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9309 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9310 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9311 }
9312 else
9313 {
9314 printf(" OFDM or CCK \n");
9315 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9316 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9317 }
9318
9319 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9320 if(rinfo[NL80211_RATE_INFO_MCS])
9321 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9322 }
9323 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9324 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9325 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9326 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9327
9328 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9329 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9330
9331 if (sinfo[NL80211_STA_INFO_SIGNAL])
9332 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9333 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9334 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9335 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9336 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9337 //rssi_array need to be filled
9338 return NL_SKIP;
9339}
9340#endif
9341
9342INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9343{
9344#ifdef HAL_NETLINK_IMPL
9345 Netlink nl;
9346 char if_name[10];
9347
9348 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9349
9350 if (*output_array_size <= 0)
9351 return RETURN_OK;
9352
9353 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9354 nl.id = initSock80211(&nl);
9355
9356 if (nl.id < 0) {
9357 fprintf(stderr, "Error initializing netlink \n");
9358 return 0;
9359 }
9360
9361 struct nl_msg* msg = nlmsg_alloc();
9362
9363 if (!msg) {
9364 fprintf(stderr, "Failed to allocate netlink message.\n");
9365 nlfree(&nl);
9366 return 0;
9367 }
9368
9369 genlmsg_put(msg,
9370 NL_AUTO_PORT,
9371 NL_AUTO_SEQ,
9372 nl.id,
9373 0,
9374 0,
9375 NL80211_CMD_GET_STATION,
9376 0);
9377
9378 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9379 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9380 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9381 nl_send_auto(nl.socket, msg);
9382 nl_recvmsgs(nl.socket, nl.cb);
9383 nlmsg_free(msg);
9384 nlfree(&nl);
9385 return RETURN_OK;
9386#else
9387 //TODO Implement me
9388 return RETURN_OK;
9389#endif
9390}
9391
9392#ifdef HAL_NETLINK_IMPL
9393static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9394 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9395 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9396 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9397 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9398 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9399 char mac_addr[20],dev[20];
9400
9401 nla_parse(tb,
9402 NL80211_ATTR_MAX,
9403 genlmsg_attrdata(gnlh, 0),
9404 genlmsg_attrlen(gnlh, 0),
9405 NULL);
9406
9407 if(!tb[NL80211_ATTR_STA_INFO]) {
9408 fprintf(stderr, "sta stats missing!\n");
9409 return NL_SKIP;
9410 }
9411
9412 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9413 fprintf(stderr, "failed to parse nested attributes!\n");
9414 return NL_SKIP;
9415 }
9416
9417 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9418
9419 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9420
9421 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9422 fprintf(stderr, "failed to parse nested rate attributes!");
9423 return NL_SKIP;
9424 }
9425
9426 if(sinfo[NL80211_STA_INFO_TID_STATS])
9427 {
9428 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9429 printf("failed to parse nested stats attributes!");
9430 return NL_SKIP;
9431 }
9432 }
9433 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9434 {
9435 printf("Type is VHT\n");
9436 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9437 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9438
9439 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9440 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9441 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9442 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9443 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9444 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9445 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9446 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9447 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9448 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9449 }
9450 else
9451 {
9452 printf(" OFDM or CCK \n");
9453 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9454 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9455 }
9456
9457 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9458 if(rinfo[NL80211_RATE_INFO_MCS])
9459 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9460 }
9461
9462 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9463 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9464 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9465 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9466
9467 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9468 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9469 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9470
9471 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9472 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9473
9474 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9475 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9476
9477 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9478 ((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]);
9479
9480 return NL_SKIP;
9481}
9482#endif
9483
9484INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9485{
9486#ifdef HAL_NETLINK_IMPL
9487 Netlink nl;
9488 char if_name[10];
9489
9490 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9491
9492 if (*output_array_size <= 0)
9493 return RETURN_OK;
9494
9495 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9496
9497 nl.id = initSock80211(&nl);
9498
9499 if(nl.id < 0) {
9500 fprintf(stderr, "Error initializing netlink \n");
9501 return 0;
9502 }
9503
9504 struct nl_msg* msg = nlmsg_alloc();
9505
9506 if(!msg) {
9507 fprintf(stderr, "Failed to allocate netlink message.\n");
9508 nlfree(&nl);
9509 return 0;
9510 }
9511
9512 genlmsg_put(msg,
9513 NL_AUTO_PORT,
9514 NL_AUTO_SEQ,
9515 nl.id,
9516 0,
9517 0,
9518 NL80211_CMD_GET_STATION,
9519 0);
9520
9521 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9522 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9523 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9524 nl_send_auto(nl.socket, msg);
9525 nl_recvmsgs(nl.socket, nl.cb);
9526 nlmsg_free(msg);
9527 nlfree(&nl);
9528 return RETURN_OK;
9529#else
9530 //TODO Implement me
9531 return RETURN_OK;
9532#endif
9533}
9534
9535INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9536{
9537 // TODO Implement me!
9538 char buf[MAX_BUF_SIZE] = {0};
9539 char config_file[MAX_BUF_SIZE] = {0};
9540
9541 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9542 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9543 *activate = (strncmp("1",buf,1) == 0);
9544
9545 return RETURN_OK;
9546}
9547
9548INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9549{
9550 char config_file[MAX_BUF_SIZE] = {0};
9551 struct params list;
9552
9553 list.name = "rrm_neighbor_report";
9554 list.value = activate?"1":"0";
9555 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9556 wifi_hostapdWrite(config_file, &list, 1);
9557
9558 return RETURN_OK;
9559}
9560
9561INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9562{
9563 char buf[32] = {0};
9564 char config_file[MAX_BUF_SIZE] = {0};
9565
9566 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9567 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9568 *activate = (strncmp("1",buf,1) == 0);
9569
9570 return RETURN_OK;
9571}
9572#undef HAL_NETLINK_IMPL
9573#ifdef HAL_NETLINK_IMPL
9574static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9575 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9576 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9577 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9578 char dev[20];
9579 int freq =0 ;
9580 static int i=0;
9581
9582 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9583
9584 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9585 };
9586
9587 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9588
9589 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9590
9591 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9592 fprintf(stderr, "survey data missing!\n");
9593 return NL_SKIP;
9594 }
9595
9596 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9597 {
9598 fprintf(stderr, "failed to parse nested attributes!\n");
9599 return NL_SKIP;
9600 }
9601
9602
9603 if(out[0].array_size == 1 )
9604 {
9605 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9606 {
9607 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9608 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9609 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9610
9611 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9612 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9613 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9614 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9615 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9616 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9617 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9618 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9619 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9620 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9621 if (sinfo[NL80211_SURVEY_INFO_TIME])
9622 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9623 return NL_STOP;
9624 }
9625 }
9626 else
9627 {
9628 if ( i <= out[0].array_size )
9629 {
9630 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9631 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9632 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9633
9634 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9635 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9636 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9637 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9638 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9639 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9640 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9641 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9642 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9643 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9644 if (sinfo[NL80211_SURVEY_INFO_TIME])
9645 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9646 }
9647 }
9648
9649 i++;
9650 return NL_SKIP;
9651}
9652#endif
9653
9654static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9655{
9656 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9657 FILE *fp;
9658
9659 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9660 {
9661 printf("Creating Frequency-Channel Map\n");
9662 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9663 }
9664 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9665 if((fp = popen(command, "r")))
9666 {
9667 fgets(output, sizeof(output), fp);
9668 *freqMHz = atoi(output);
9669 fclose(fp);
9670 }
9671
9672 return 0;
9673}
9674
9675static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9676{
9677 int freqMHz = -1;
9678 char cmd[MAX_CMD_SIZE] = {'\0'};
9679
9680 ieee80211_channel_to_frequency(channel, &freqMHz);
9681 if (freqMHz == -1) {
9682 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9683 return -1;
9684 }
9685
9686 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9687 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9688 radioIndex, freqMHz);
9689 return -1;
9690 }
9691
9692 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9693 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9694 return -1;
9695 }
9696
9697 return 0;
9698}
9699
9700static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9701{
9702 const char *ptr = buf;
9703 char *key = NULL;
9704 char *val = NULL;
9705 char line[256] = { '\0' };
9706
9707 while (ptr = get_line_from_str_buf(ptr, line)) {
9708 if (strstr(line, "Frequency")) continue;
9709
9710 key = strtok(line, ":");
9711 val = strtok(NULL, " ");
9712 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9713
9714 if (!strcmp(key, "noise")) {
9715 sscanf(val, "%d", &stats->ch_noise);
9716 if (stats->ch_noise == 0) {
9717 // Workaround for missing noise information.
9718 // Assume -95 for 2.4G and -103 for 5G
9719 if (radioIndex == 0) stats->ch_noise = -95;
9720 if (radioIndex == 1) stats->ch_noise = -103;
9721 }
9722 }
9723 else if (!strcmp(key, "channel active time")) {
9724 sscanf(val, "%llu", &stats->ch_utilization_total);
9725 }
9726 else if (!strcmp(key, "channel busy time")) {
9727 sscanf(val, "%llu", &stats->ch_utilization_busy);
9728 }
9729 else if (!strcmp(key, "channel receive time")) {
9730 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9731 }
9732 else if (!strcmp(key, "channel transmit time")) {
9733 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9734 }
9735 };
9736
9737 return 0;
9738}
9739
9740INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9741{
9742 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9743#ifdef HAL_NETLINK_IMPL
9744 Netlink nl;
9745 wifi_channelStats_t_loc local[array_size];
9746 char if_name[10];
9747
9748 local[0].array_size = array_size;
9749
9750 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9751
9752 nl.id = initSock80211(&nl);
9753
9754 if (nl.id < 0) {
9755 fprintf(stderr, "Error initializing netlink \n");
9756 return -1;
9757 }
9758
9759 struct nl_msg* msg = nlmsg_alloc();
9760
9761 if (!msg) {
9762 fprintf(stderr, "Failed to allocate netlink message.\n");
9763 nlfree(&nl);
9764 return -2;
9765 }
9766
9767 genlmsg_put(msg,
9768 NL_AUTO_PORT,
9769 NL_AUTO_SEQ,
9770 nl.id,
9771 0,
9772 NLM_F_DUMP,
9773 NL80211_CMD_GET_SURVEY,
9774 0);
9775
9776 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9777 nl_send_auto(nl.socket, msg);
9778 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9779 nl_recvmsgs(nl.socket, nl.cb);
9780 nlmsg_free(msg);
9781 nlfree(&nl);
9782 //Copying the Values
9783 for(int i=0;i<array_size;i++)
9784 {
9785 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9786 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9787 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9788 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9789 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9790 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9791 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9792 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9793 }
9794#else
9795 ULONG channel = 0;
9796 int i;
9797 int number_of_channels = array_size;
9798 char buf[512];
9799 INT ret;
9800 wifi_channelStats_t tmp_stats;
9801
9802 if (number_of_channels == 0) {
9803 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9804 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9805 return RETURN_ERR;
9806 }
9807 number_of_channels = 1;
9808 input_output_channelStats_array[0].ch_number = channel;
9809 }
9810
9811 for (i = 0; i < number_of_channels; i++) {
9812
9813 input_output_channelStats_array[i].ch_noise = 0;
9814 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9815 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9816 input_output_channelStats_array[i].ch_utilization_busy = 0;
9817 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9818 input_output_channelStats_array[i].ch_utilization_total = 0;
9819
9820 memset(buf, 0, sizeof(buf));
9821 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9822 return RETURN_ERR;
9823 }
9824 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9825 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9826 return RETURN_ERR;
9827 }
9828
9829 // XXX: fake missing 'self' counter which is not available in iw survey output
9830 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9831 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9832
9833 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9834 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9835 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9836 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9837 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9838
9839 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",
9840 __func__,
9841 input_output_channelStats_array[i].ch_number,
9842 input_output_channelStats_array[i].ch_noise,
9843 input_output_channelStats_array[i].ch_utilization_total,
9844 input_output_channelStats_array[i].ch_utilization_busy,
9845 input_output_channelStats_array[i].ch_utilization_busy_rx,
9846 input_output_channelStats_array[i].ch_utilization_busy_tx,
9847 input_output_channelStats_array[i].ch_utilization_busy_self,
9848 input_output_channelStats_array[i].ch_utilization_busy_ext);
9849 }
9850#endif
9851 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9852 return RETURN_OK;
9853}
9854#define HAL_NETLINK_IMPL
9855
9856/* Hostapd events */
9857
9858#ifndef container_of
9859#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9860#define container_of(ptr, type, member) \
9861 ((type *)((char *)ptr - offset_of(type, member)))
9862#endif /* container_of */
9863
9864struct ctrl {
9865 char sockpath[128];
9866 char sockdir[128];
9867 char bss[IFNAMSIZ];
9868 char reply[4096];
9869 int ssid_index;
9870 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9871 void (*overrun)(struct ctrl *ctrl);
9872 struct wpa_ctrl *wpa;
9873 unsigned int ovfl;
9874 size_t reply_len;
9875 int initialized;
9876 ev_timer retry;
9877 ev_timer watchdog;
9878 ev_stat stat;
9879 ev_io io;
9880};
9881static wifi_newApAssociatedDevice_callback clients_connect_cb;
9882static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9883static struct ctrl wpa_ctrl[MAX_APS];
9884static int initialized;
9885
9886static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9887{
9888 char cbuf[256] = {};
9889 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9890 struct cmsghdr *cmsg;
9891 unsigned int ovfl = ctrl->ovfl;
9892 unsigned int drop;
9893
9894 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9895 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9896 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9897 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9898
9899 drop = ovfl - ctrl->ovfl;
9900 ctrl->ovfl = ovfl;
9901
9902 return drop;
9903}
9904
9905static void ctrl_close(struct ctrl *ctrl)
9906{
9907 if (ctrl->io.cb)
9908 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9909 if (ctrl->retry.cb)
9910 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9911 if (!ctrl->wpa)
9912 return;
9913
9914 wpa_ctrl_detach(ctrl->wpa);
9915 wpa_ctrl_close(ctrl->wpa);
9916 ctrl->wpa = NULL;
9917 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9918}
9919
9920static void ctrl_process(struct ctrl *ctrl)
9921{
9922 const char *str;
9923 int drops;
9924 int level;
9925 int err;
9926
9927 /* Example events:
9928 *
9929 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9930 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9931 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9932 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9933 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9934 */
9935 if (!(str = index(ctrl->reply, '>')))
9936 return;
9937 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9938 return;
9939
9940 str++;
9941
9942 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9943 if (!(str = index(ctrl->reply, ' ')))
9944 return;
9945 wifi_associated_dev_t sta;
9946 memset(&sta, 0, sizeof(sta));
9947
9948 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9949 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9950 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9951
9952 sta.cli_Active=true;
9953
9954 (clients_connect_cb)(ctrl->ssid_index, &sta);
9955 goto handled;
9956 }
9957
9958 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9959 if (!(str = index(ctrl->reply, ' ')))
9960 return;
9961
9962 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9963 goto handled;
9964 }
9965
9966 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9967 printf("CTRL_WPA: handle TERMINATING event\n");
9968 goto retry;
9969 }
9970
9971 if (strncmp("AP-DISABLED", str, 11) == 0) {
9972 printf("CTRL_WPA: handle AP-DISABLED\n");
9973 goto retry;
9974 }
9975
9976 printf("Event not supported!!\n");
9977
9978handled:
9979
9980 if ((drops = ctrl_get_drops(ctrl))) {
9981 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
9982 if (ctrl->overrun)
9983 ctrl->overrun(ctrl);
9984 }
9985
9986 return;
9987
9988retry:
9989 printf("WPA_CTRL: closing\n");
9990 ctrl_close(ctrl);
9991 printf("WPA_CTRL: retrying from ctrl prcoess\n");
9992 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
9993}
9994
9995static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
9996{
9997 struct ctrl *ctrl = container_of(io, struct ctrl, io);
9998 int err;
9999
10000 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10001 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10002 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10003 ctrl->reply[ctrl->reply_len] = 0;
10004 if (err < 0) {
10005 if (errno == EAGAIN || errno == EWOULDBLOCK)
10006 return;
10007 ctrl_close(ctrl);
10008 ev_timer_again(EV_A_ &ctrl->retry);
10009 return;
10010 }
10011
10012 ctrl_process(ctrl);
10013}
10014
10015static int ctrl_open(struct ctrl *ctrl)
10016{
10017 int fd;
10018
10019 if (ctrl->wpa)
10020 return 0;
10021
10022 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10023 if (!ctrl->wpa)
10024 goto err;
10025
10026 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10027 goto err_close;
10028
10029 fd = wpa_ctrl_get_fd(ctrl->wpa);
10030 if (fd < 0)
10031 goto err_detach;
10032
10033 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10034 goto err_detach;
10035
10036 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10037 ev_io_start(EV_DEFAULT_ &ctrl->io);
10038
10039 return 0;
10040
10041err_detach:
10042 wpa_ctrl_detach(ctrl->wpa);
10043err_close:
10044 wpa_ctrl_close(ctrl->wpa);
10045err:
10046 ctrl->wpa = NULL;
10047 return -1;
10048}
10049
10050static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10051{
10052 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10053
10054 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10055 ctrl_open(ctrl);
10056}
10057
10058static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10059{
10060 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10061
10062 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10063 if (ctrl_open(ctrl) == 0) {
10064 printf("WPA_CTRL: retry successful\n");
10065 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10066 }
10067}
10068
10069int ctrl_enable(struct ctrl *ctrl)
10070{
10071 if (ctrl->wpa)
10072 return 0;
10073
10074 if (!ctrl->stat.cb) {
10075 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10076 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10077 }
10078
10079 if (!ctrl->retry.cb) {
10080 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10081 }
10082
10083 return ctrl_open(ctrl);
10084}
10085
10086static void
10087ctrl_msg_cb(char *buf, size_t len)
10088{
10089 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10090
10091 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10092 ctrl_process(ctrl);
10093}
10094
10095static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10096{
10097 int err;
10098
10099 if (!ctrl->wpa)
10100 return -1;
10101 if (*reply_len < 2)
10102 return -1;
10103
10104 (*reply_len)--;
10105 ctrl->reply_len = sizeof(ctrl->reply);
10106 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10107 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10108 if (err < 0)
10109 return err;
10110
10111 if (ctrl->reply_len > *reply_len)
10112 ctrl->reply_len = *reply_len;
10113
10114 *reply_len = ctrl->reply_len;
10115 memcpy(reply, ctrl->reply, *reply_len);
10116 reply[*reply_len - 1] = 0;
10117 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10118 return 0;
10119}
10120
10121static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10122{
10123 const char *pong = "PONG";
10124 const char *ping = "PING";
10125 char reply[1024];
10126 size_t len = sizeof(reply);
10127 int err;
10128 ULONG s, snum;
10129 INT ret;
10130 BOOL status;
10131
10132 printf("WPA_CTRL: watchdog cb\n");
10133
10134 ret = wifi_getSSIDNumberOfEntries(&snum);
10135 if (ret != RETURN_OK) {
10136 printf("%s: failed to get SSID count", __func__);
10137 return;
10138 }
10139
10140 if (snum > MAX_APS) {
10141 printf("more ssid than supported! %lu\n", snum);
10142 return;
10143 }
10144
10145 for (s = 0; s < snum; s++) {
10146 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10147 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10148 continue;
10149 }
10150 if (status == false) continue;
10151
10152 memset(reply, 0, sizeof(reply));
10153 len = sizeof(reply);
10154 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10155 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10156 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10157 continue;
10158
10159 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10160 ctrl_close(&wpa_ctrl[s]);
10161 printf("WPA_CTRL: ev_timer_again %d\n", s);
10162 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10163 }
10164}
10165
10166static int init_wpa()
10167{
10168 int ret = 0, i = 0;
10169 ULONG s, snum;
10170
10171 ret = wifi_getSSIDNumberOfEntries(&snum);
10172 if (ret != RETURN_OK) {
10173 printf("%s: failed to get SSID count", __func__);
10174 return RETURN_ERR;
10175 }
10176
10177 if (snum > MAX_APS) {
10178 printf("more ssid than supported! %lu\n", snum);
10179 return RETURN_ERR;
10180 }
10181
10182 for (s = 0; s < snum; s++) {
10183 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10184 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10185 wpa_ctrl[s].ssid_index = s;
10186 ctrl_enable(&wpa_ctrl[s]);
10187 }
10188
10189 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10190 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10191
10192 initialized = 1;
10193 printf("WPA_CTRL: initialized\n");
10194
10195 return RETURN_OK;
10196}
10197
10198void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10199{
10200 clients_connect_cb = callback_proc;
10201 if (!initialized)
10202 init_wpa();
10203}
10204
10205void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10206{
10207 clients_disconnect_cb = callback_proc;
10208 if (!initialized)
10209 init_wpa();
10210}
10211
10212INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10213{
10214 // TODO Implement me!
10215 return RETURN_ERR;
10216}
10217
10218INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10219{
10220 // TODO Implement me!
10221 return RETURN_ERR;
10222}
10223
10224INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10225{
10226 int i;
10227 char cmd[256];
10228 char channel_numbers_buf[256];
10229 char dfs_state_buf[256];
10230 char line[256];
10231 const char *ptr;
10232
10233 memset(cmd, 0, sizeof(cmd));
10234 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10235 memset(line, 0, sizeof(line));
10236 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10237 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10238
10239 if (radioIndex == 0) { // 2.4G - all allowed
10240 if (outputMapSize < 11) {
10241 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10242 return RETURN_ERR;
10243 }
10244
10245 for (i = 0; i < 11; i++) {
10246 outputMap[i].ch_number = i + 1;
10247 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10248 }
10249
10250 return RETURN_OK;
10251 }
10252
10253 if (radioIndex == 1) { // 5G
10254// Example output of iw list:
10255//
10256// Frequencies:
10257// * 5180 MHz [36] (17.0 dBm)
10258// * 5200 MHz [40] (17.0 dBm)
10259// * 5220 MHz [44] (17.0 dBm)
10260// * 5240 MHz [48] (17.0 dBm)
10261// * 5260 MHz [52] (23.0 dBm) (radar detection)
10262// DFS state: usable (for 78930 sec)
10263// DFS CAC time: 60000 ms
10264// * 5280 MHz [56] (23.0 dBm) (radar detection)
10265// DFS state: usable (for 78930 sec)
10266// DFS CAC time: 60000 ms
10267// * 5300 MHz [60] (23.0 dBm) (radar detection)
10268// DFS state: usable (for 78930 sec)
10269// DFS CAC time: 60000 ms
10270// * 5320 MHz [64] (23.0 dBm) (radar detection)
10271// DFS state: usable (for 78930 sec)
10272// DFS CAC time: 60000 ms
10273// * 5500 MHz [100] (disabled)
10274// * 5520 MHz [104] (disabled)
10275// * 5540 MHz [108] (disabled)
10276// * 5560 MHz [112] (disabled)
10277//
10278// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10279 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10280 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10281 return RETURN_ERR;
10282 }
10283
10284 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10285 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10286 return RETURN_ERR;
10287 }
10288
10289 ptr = channel_numbers_buf;
10290 i = 0;
10291 while (ptr = get_line_from_str_buf(ptr, line)) {
10292 if (i >= outputMapSize) {
10293 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10294 return RETURN_ERR;
10295 }
10296 sscanf(line, "%d", &outputMap[i].ch_number);
10297
10298 memset(cmd, 0, sizeof(cmd));
10299 // Below command should fetch string for DFS state (usable, available or unavailable)
10300 // Example line: "DFS state: usable (for 78930 sec)"
10301 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) {
10302 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10303 return RETURN_ERR;
10304 }
10305
10306 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10307 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10308 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10309 return RETURN_ERR;
10310 }
10311
10312 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10313
10314 if (!strcmp(dfs_state_buf, "usable")) {
10315 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10316 } else if (!strcmp(dfs_state_buf, "available")) {
10317 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10318 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10319 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10320 } else {
10321 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10322 }
10323 i++;
10324 }
10325
10326 return RETURN_OK;
10327 }
10328
10329 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10330 return RETURN_ERR;
10331}
10332
10333INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10334{
10335 // TODO Implement me!
10336 return RETURN_ERR;
10337}
10338
10339INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10340{
10341 return RETURN_OK;
10342}
10343
10344INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10345{
10346 // TODO Implement me!
10347 return RETURN_ERR;
10348}
10349
10350INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10351{
10352 // TODO API refrence Implementaion is present on RPI hal
10353 return RETURN_ERR;
10354}
10355
10356INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10357{
developera5005b62022-09-13 15:43:35 +080010358 char cmd[128]={'\0'};
10359 char buf[128]={'\0'};
10360 char *support;
10361 int maximum_tx = 0, current_tx = 0;
10362
10363 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10364 if(txpwr_pcntg == NULL)
10365 return RETURN_ERR;
10366
10367 // Get the maximum tx power of the device
10368 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10369 _syscmd(cmd, buf, sizeof(buf));
10370 maximum_tx = strtol(buf, NULL, 10);
10371
10372 // Get the current tx power
10373 memset(cmd, 0, sizeof(cmd));
10374 memset(buf, 0, sizeof(buf));
10375 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10376 _syscmd(cmd, buf, sizeof(buf));
10377 current_tx = strtol(buf, NULL, 10);
10378
10379 // Get the power supported list and find the current power percentage in supported list
10380 memset(buf, 0, sizeof(buf));
10381 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10382 support = strtok(buf, ",");
10383 while(true)
10384 {
10385 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10386 *txpwr_pcntg = 0;
10387 wifi_dbg_printf("current power is not in supported list\n");
10388 return RETURN_ERR;
10389 }
10390 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10391 if (tmp == current_tx) {
10392 *txpwr_pcntg = strtol(support, NULL, 10);
10393 break;
10394 }
10395 support = strtok(NULL, ",");
10396 }
10397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010398 return RETURN_OK;
10399}
10400
10401INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10402{
developer58599c22022-09-13 16:40:34 +080010403 // TODO precac feature.
10404 struct params params = {0};
10405 char config_file[128] = {0};
10406
10407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10408
10409 params.name = "enable_background_radar";
10410 params.value = enable?"1":"0";
10411 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10412 wifi_hostapdWrite(config_file, &params, 1);
10413 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10414
10415 /* TODO precac feature */
10416
10417 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10418 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010419}
10420
10421INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10422{
developer58599c22022-09-13 16:40:34 +080010423 char config_file[128] = {0};
10424 char buf[64] = {0};
10425
10426 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10427 if (NULL == enable || NULL == precac)
10428 return RETURN_ERR;
10429
10430 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10431 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10432 if (strncmp(enable, "1", 1) == 0)
10433 *enable = true;
10434 else
10435 *enable = false;
10436
10437 /* TODO precac feature */
10438
10439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10440 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010441}
10442
10443INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10444{
developer58599c22022-09-13 16:40:34 +080010445 *supported = TRUE;
10446 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010447}
10448
developer3e6b1692022-09-30 18:04:05 +080010449INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10450{
10451 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10452 struct params params = {0};
10453 char config_file[64] = {0};
10454 char buf[64] = {0};
10455 unsigned int set_mu_type = 0;
10456 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10457
10458 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10459 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10460
10461 if (strlen(buf) > 0)
10462 set_mu_type = strtol(buf, NULL, 10);
10463
10464 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10465 set_mu_type &= ~0x05; // unset bit 0, 2
10466 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10467 set_mu_type |= 0x01;
10468 set_mu_type &= ~0x04;
10469 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10470 set_mu_type &= ~0x01;
10471 set_mu_type |= 0x04;
10472 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10473 set_mu_type |= 0x05; // set bit 0, 2
10474 }
10475
10476 params.name = "hemu_onoff";
10477 sprintf(buf, "%u", set_mu_type);
10478 params.value = buf;
10479 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10480 wifi_hostapdWrite(config_file, &params, 1);
10481 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10482
10483 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10484 return RETURN_OK;
10485}
10486
10487INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10488{
10489 struct params params={0};
10490 char config_file[64] = {0};
10491 char buf[64] = {0};
10492 unsigned int get_mu_type = 0;
10493
10494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10495
10496 if (mu_type == NULL)
10497 return RETURN_ERR;
10498
10499 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10500 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10501 get_mu_type = strtol(buf, NULL, 10);
10502
10503 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10504 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10505 else if (get_mu_type & 0x04)
10506 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10507 else if (get_mu_type & 0x01)
10508 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10509 else
10510 *mu_type = WIFI_DL_MU_TYPE_NONE;
10511
10512 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10513 return RETURN_OK;
10514}
10515
10516INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10517{
10518 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10519 struct params params={0};
10520 char config_file[64] = {0};
10521 char buf[64] = {0};
10522 unsigned int set_mu_type = 0;
10523 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10524
10525 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10526 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10527
10528 if (strlen(buf) > 0)
10529 set_mu_type = strtol(buf, NULL, 10);
10530
10531 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10532 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10533 set_mu_type &= ~0x0a;
10534 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10535 set_mu_type |= 0x02;
10536 set_mu_type &= ~0x08;
10537 }
10538
10539 params.name = "hemu_onoff";
10540 sprintf(buf, "%u", set_mu_type);
10541 params.value = buf;
10542 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10543 wifi_hostapdWrite(config_file, &params, 1);
10544 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10545
10546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10547 return RETURN_OK;
10548}
10549
10550INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10551{
10552 struct params params={0};
10553 char config_file[64] = {0};
10554 char buf[64] = {0};
10555 unsigned int get_mu_type = 0;
10556
10557 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10558
10559 if (mu_type == NULL)
10560 return RETURN_ERR;
10561
10562 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10563 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10564
10565 get_mu_type = strtol(buf, NULL, 10);
10566 if (get_mu_type & 0x02)
10567 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10568 else
10569 *mu_type = WIFI_DL_MU_TYPE_NONE;
10570
10571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10572 return RETURN_OK;
10573}
10574
10575
developer454b9462022-09-13 15:29:16 +080010576INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10577{
10578 char cmd[128] = {0};
10579 char buf[64] = {0};
10580 char band_str[8] = {0};
10581 char GI[8] = {0};
10582 int tmp = 0;
10583 BOOL ax_mode = FALSE;
10584 BOOL short_GI = FALSE;
10585 FILE *f = NULL;
10586 wifi_band band;
10587
10588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10589
10590 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
10591 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10592 return RETURN_ERR;
10593 }
10594 if (strstr(buf, "ax") != NULL)
10595 ax_mode = TRUE;
10596
10597 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
10598 short_GI = TRUE;
10599 strcpy(GI, "0.4");
10600 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
10601 strcpy(GI, "1.6");
10602 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
10603 strcpy(GI, "3.2");
10604 else // default
10605 strcpy(GI, "0.8");
10606
10607 band = wifi_index_to_band(radio_index);
10608 if (band == band_2_4)
10609 strcpy(band_str, "2.4");
10610 else if (band == band_5)
10611 strcpy(band_str, "5");
10612 else if (band == band_6)
10613 strcpy(band_str, "6");
10614 else {
10615 wifi_dbg_printf("%s: invalid band\n");
10616 return RETURN_ERR;
10617 }
10618
10619 if (ax_mode == TRUE)
10620 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
10621 else
10622 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
10623 _syscmd(cmd, buf, sizeof(buf));
10624
10625 // Record GI for get GI function
10626 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10627 f = fopen(buf, "w");
10628 if (f != NULL) {
10629 fprintf(f, "%s", GI);
10630 }
10631 fclose(f);
10632 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10633 return RETURN_OK;
10634}
10635
10636INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10637{
10638 char buf[32] = {0};
10639 char cmd[64] = {0};
10640
10641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10642
10643 if (guard_interval == NULL)
10644 return RETURN_ERR;
10645
10646 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10647 _syscmd(cmd, buf, sizeof(buf));
10648
10649 if (strncmp(buf, "0.4", 3) == 0)
10650 *guard_interval = wifi_guard_interval_400;
10651 else if (strncmp(buf, "0.8", 3) == 0)
10652 *guard_interval = wifi_guard_interval_800;
10653 else if (strncmp(buf, "1.6", 3) == 0)
10654 *guard_interval = wifi_guard_interval_1600;
10655 else if (strncmp(buf, "3.2", 3) == 0)
10656 *guard_interval = wifi_guard_interval_3200;
10657 else
10658 *guard_interval = wifi_guard_interval_auto;
10659
10660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10661 return RETURN_OK;
10662}
10663
developer3cc61d12022-09-13 16:36:05 +080010664INT wifi_setBSSColor(INT radio_index, UCHAR color)
10665{
10666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10667 struct params params = {0};
10668 char config_file[128] = {0};
10669 char bss_color[4] ={0};
10670
10671 params.name = "he_bss_color";
10672 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10673 params.value = bss_color;
10674 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10675 wifi_hostapdWrite(config_file, &params, 1);
10676 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10677
10678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10679 return RETURN_OK;
10680}
10681
10682INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10683{
10684 char config_file[128] = {0};
10685 char buf[64] = {0};
10686 char temp_output[128] = {'\0'};
10687
10688 wifi_dbg_printf("\nFunc=%s\n", __func__);
10689 if (NULL == color)
10690 return RETURN_ERR;
10691
10692 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10693 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10694
10695 if(strlen(buf) > 0) {
10696 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10697 } else {
10698 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10699 }
10700
10701 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10702 wifi_dbg_printf("\noutput_string=%s\n", color);
10703
10704 return RETURN_OK;
10705}
10706
developer06a01d92022-09-07 16:32:39 +080010707/* multi-psk support */
10708INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10709{
10710 char cmd[256];
10711
10712 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10713 AP_PREFIX,
10714 apIndex,
10715 mac[0],
10716 mac[1],
10717 mac[2],
10718 mac[3],
10719 mac[4],
10720 mac[5]
10721 );
10722 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10723 _syscmd(cmd, key->wifi_keyId, 64);
10724
10725
10726 return RETURN_OK;
10727}
10728
10729INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10730{
10731 FILE *fd = NULL;
10732 char fname[100];
10733 char cmd[128] = {0};
10734 char out[64] = {0};
10735 wifi_key_multi_psk_t * key = NULL;
10736 if(keysNumber < 0)
10737 return RETURN_ERR;
10738
10739 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10740 fd = fopen(fname, "w");
10741 if (!fd) {
10742 return RETURN_ERR;
10743 }
10744 key= (wifi_key_multi_psk_t *) keys;
10745 for(int i=0; i<keysNumber; ++i, key++) {
10746 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10747 }
10748 fclose(fd);
10749
10750 //reload file
10751 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10752 _syscmd(cmd, out, 64);
10753 return RETURN_OK;
10754}
10755
10756INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10757{
10758 FILE *fd = NULL;
10759 char fname[100];
10760 char * line = NULL;
10761 char * pos = NULL;
10762 size_t len = 0;
10763 ssize_t read = 0;
10764 INT ret = RETURN_OK;
10765 wifi_key_multi_psk_t *keys_it = NULL;
10766
10767 if (keysNumber < 1) {
10768 return RETURN_ERR;
10769 }
10770
10771 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10772 fd = fopen(fname, "r");
10773 if (!fd) {
10774 return RETURN_ERR;
10775 }
10776
10777 if (keys == NULL) {
10778 ret = RETURN_ERR;
10779 goto close;
10780 }
10781
10782 keys_it = keys;
10783 while ((read = getline(&line, &len, fd)) != -1) {
10784 //Strip trailing new line if present
10785 if (read > 0 && line[read-1] == '\n') {
10786 line[read-1] = '\0';
10787 }
10788
10789 if(strcmp(line,"keyid=")) {
10790 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10791 if (!(pos = index(line, ' '))) {
10792 ret = RETURN_ERR;
10793 goto close;
10794 }
10795 pos++;
10796 //Here should be 00:00:00:00:00:00
10797 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10798 printf("Not supported MAC: %s\n", pos);
10799 }
10800 if (!(pos = index(pos, ' '))) {
10801 ret = RETURN_ERR;
10802 goto close;
10803 }
10804 pos++;
10805
10806 //The rest is PSK
10807 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10808 keys_it++;
10809
10810 if(--keysNumber <= 0)
10811 break;
10812 }
10813 }
10814
10815close:
10816 free(line);
10817 fclose(fd);
10818 return ret;
10819}
10820/* end of multi-psk support */
10821
10822INT wifi_setNeighborReports(UINT apIndex,
10823 UINT numNeighborReports,
10824 wifi_NeighborReport_t *neighborReports)
10825{
10826 char cmd[256] = { 0 };
10827 char hex_bssid[13] = { 0 };
10828 char bssid[18] = { 0 };
10829 char nr[256] = { 0 };
10830 char ssid[256];
10831 char hex_ssid[256];
10832 INT ret;
10833
10834 /*rmeove all neighbors*/
10835 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10836 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);
10837 system(cmd);
10838
10839 for(unsigned int i = 0; i < numNeighborReports; i++)
10840 {
10841 memset(ssid, 0, sizeof(ssid));
10842 ret = wifi_getSSIDName(apIndex, ssid);
10843 if (ret != RETURN_OK)
10844 return RETURN_ERR;
10845
10846 memset(hex_ssid, 0, sizeof(hex_ssid));
10847 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10848 sprintf(hex_ssid + k,"%02x", ssid[j]);
10849
10850 snprintf(hex_bssid, sizeof(hex_bssid),
10851 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10852 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10853 snprintf(bssid, sizeof(bssid),
10854 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10855 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10856
10857 snprintf(nr, sizeof(nr),
10858 "%s" // bssid
10859 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10860 "%02hhx" // operclass
10861 "%02hhx" // channel
10862 "%02hhx", // phy_mode
10863 hex_bssid,
10864 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10865 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10866 neighborReports[i].opClass,
10867 neighborReports[i].channel,
10868 neighborReports[i].phyTable);
10869
10870 snprintf(cmd, sizeof(cmd),
10871 "hostapd_cli set_neighbor "
10872 "%s " // bssid
10873 "ssid=%s " // ssid
10874 "nr=%s " // nr
10875 "-i %s%d",
10876 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10877
10878 if (WEXITSTATUS(system(cmd)) != 0)
10879 {
10880 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10881 }
10882 }
10883
10884 return RETURN_OK;
10885}
10886
10887INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10888{
10889 return RETURN_OK;
10890}
10891
10892#ifdef _WIFI_HAL_TEST_
10893int main(int argc,char **argv)
10894{
10895 int index;
10896 INT ret=0;
10897 char buf[1024]="";
10898
10899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10900 if(argc<3)
10901 {
10902 if(argc==2)
10903 {
10904 if(!strcmp(argv[1], "init"))
10905 return wifi_init();
10906 if(!strcmp(argv[1], "reset"))
10907 return wifi_reset();
10908 if(!strcmp(argv[1], "wifi_getHalVersion"))
10909 {
10910 char buffer[64];
10911 if(wifi_getHalVersion(buffer)==RETURN_OK)
10912 printf("Version: %s\n", buffer);
10913 else
10914 printf("Error in wifi_getHalVersion\n");
10915 return RETURN_OK;
10916 }
10917 }
10918 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10919 exit(-1);
10920 }
10921
10922 index = atoi(argv[2]);
10923 if(strstr(argv[1], "wifi_getApName")!=NULL)
10924 {
10925 wifi_getApName(index,buf);
10926 printf("Ap name is %s \n",buf);
10927 return 0;
10928 }
10929 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10930 {
10931 BOOL b = FALSE;
10932 BOOL *output_bool = &b;
10933 wifi_getRadioAutoChannelEnable(index,output_bool);
10934 printf("Channel enabled = %d \n",b);
10935 return 0;
10936 }
10937 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10938 {
10939 wifi_getApWpaEncryptionMode(index,buf);
10940 printf("encryption enabled = %s\n",buf);
10941 return 0;
10942 }
10943 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10944 {
10945 BOOL b = FALSE;
10946 BOOL *output_bool = &b;
10947 wifi_getApSsidAdvertisementEnable(index,output_bool);
10948 printf("advertisment enabled = %d\n",b);
10949 return 0;
10950 }
10951 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10952 {
10953 if(argc <= 3 )
10954 {
10955 printf("Insufficient arguments \n");
10956 exit(-1);
10957 }
10958
10959 char sta[20] = {'\0'};
10960 ULLONG handle= 0;
10961 strcpy(sta,argv[3]);
10962 mac_address_t st;
10963 mac_addr_aton(st,sta);
10964
10965 wifi_associated_dev_tid_stats_t tid_stats;
10966 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10967 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10968 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);
10969 }
10970
10971 if(strstr(argv[1], "getApEnable")!=NULL) {
10972 BOOL enable;
10973 ret=wifi_getApEnable(index, &enable);
10974 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10975 }
10976 else if(strstr(argv[1], "setApEnable")!=NULL) {
10977 BOOL enable = atoi(argv[3]);
10978 ret=wifi_setApEnable(index, enable);
10979 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10980 }
10981 else if(strstr(argv[1], "getApStatus")!=NULL) {
10982 char status[64];
10983 ret=wifi_getApStatus(index, status);
10984 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
10985 }
10986 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
10987 {
10988 wifi_getSSIDNameStatus(index,buf);
10989 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
10990 return 0;
10991 }
10992 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
10993 wifi_ssidTrafficStats2_t stats={0};
10994 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
10995 printf("%s %d: returns %d\n", argv[1], index, ret);
10996 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
10997 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
10998 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
10999 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11000 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11001 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11002 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11003 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11004 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11005 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11006 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11007 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11008 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11009 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11010 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11011 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11012 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11013 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11014 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11015 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11016 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11017 }
11018 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11019 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11020 UINT array_size=0;
11021 UINT i=0;
11022 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11023 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11024 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11025 printf(" neighbor %d:\n", i);
11026 printf(" ap_SSID =%s\n", pt->ap_SSID);
11027 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11028 printf(" ap_Mode =%s\n", pt->ap_Mode);
11029 printf(" ap_Channel =%d\n", pt->ap_Channel);
11030 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11031 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11032 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11033 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11034 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11035 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11036 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11037 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11038 printf(" ap_Noise =%d\n", pt->ap_Noise);
11039 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11040 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11041 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11042 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11043 }
11044 if(neighbor_ap_array)
11045 free(neighbor_ap_array); //make sure to free the list
11046 }
11047 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11048 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11049 UINT array_size=0;
11050 UINT i=0;
11051 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11052 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11053 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11054 printf(" associated_dev %d:\n", i);
11055 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11056 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11057 printf(" cli_SNR =%d\n", pt->cli_SNR);
11058 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11059 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11060 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11061 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11062 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11063 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11064 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11065 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11066 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11067 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11068 }
11069 if(associated_dev_array)
11070 free(associated_dev_array); //make sure to free the list
11071 }
11072
11073 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11074 {
11075#define MAX_ARRAY_SIZE 64
11076 int i, array_size;
11077 char *p, *ch_str;
11078 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11079
11080 if(argc != 5)
11081 {
11082 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11083 exit(-1);
11084 }
11085 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11086
11087 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11088 {
11089 strtok_r(ch_str, ",", &p);
11090 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11091 }
11092 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11093 if(!array_size)
11094 array_size=1;//Need to print current channel statistics
11095 for(i=0; i<array_size; i++)
11096 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11097 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11098 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11099 input_output_channelStats_array[i].ch_number,\
11100 input_output_channelStats_array[i].ch_noise,\
11101 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11102 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11103 input_output_channelStats_array[i].ch_utilization_busy,\
11104 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11105 input_output_channelStats_array[i].ch_utilization_total);
11106 }
11107
11108 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11109 {
11110 if(argc <= 3 )
11111 {
11112 printf("Insufficient arguments \n");
11113 exit(-1);
11114 }
11115 char mac_addr[20] = {'\0'};
11116 wifi_device_t output_struct;
11117 int dev_index = atoi(argv[3]);
11118
11119 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11120 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11121 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);
11122 }
11123
11124 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11125 {
11126 if (argc <= 3)
11127 {
11128 printf("Insufficient arguments\n");
11129 exit(-1);
11130 }
11131 char args[256];
11132 wifi_NeighborReport_t *neighborReports;
11133
11134 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11135 if (!neighborReports)
11136 {
11137 printf("Failed to allocate memory");
11138 exit(-1);
11139 }
11140
11141 for (int i = 3; i < argc; ++i)
11142 {
11143 char *val;
11144 int j = 0;
11145 memset(args, 0, sizeof(args));
11146 strncpy(args, argv[i], sizeof(args));
11147 val = strtok(args, ";");
11148 while (val != NULL)
11149 {
11150 if (j == 0)
11151 {
11152 mac_addr_aton(neighborReports[i - 3].bssid, val);
11153 } else if (j == 1)
11154 {
11155 neighborReports[i - 3].info = strtol(val, NULL, 16);
11156 } else if (j == 2)
11157 {
11158 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11159 } else if (j == 3)
11160 {
11161 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11162 } else if (j == 4)
11163 {
11164 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11165 } else {
11166 printf("Insufficient arguments]n\n");
11167 exit(-1);
11168 }
11169 val = strtok(NULL, ";");
11170 j++;
11171 }
11172 }
11173
11174 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11175 if (ret != RETURN_OK)
11176 {
11177 printf("wifi_setNeighborReports ret = %d", ret);
11178 exit(-1);
11179 }
11180 }
11181 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11182 {
11183 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11184 printf("%s.\n", buf);
11185 else
11186 printf("Error returned\n");
11187 }
11188 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11189 {
11190 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11191 printf("%s.\n", buf);
11192 else
11193 printf("Error returned\n");
11194 }
11195 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11196 {
11197 if (argc <= 2)
11198 {
11199 printf("Insufficient arguments\n");
11200 exit(-1);
11201 }
11202 char buf[64]= {'\0'};
11203 wifi_getRadioOperatingChannelBandwidth(index,buf);
11204 printf("Current bandwidth is %s \n",buf);
11205 return 0;
11206 }
11207 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11208 {
11209 if (argc <= 5)
11210 {
11211 printf("Insufficient arguments\n");
11212 exit(-1);
11213 }
11214 UINT channel = atoi(argv[3]);
11215 UINT width = atoi(argv[4]);
11216 UINT beacon = atoi(argv[5]);
11217 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11218 printf("Result = %d", ret);
11219 }
11220
11221 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11222 return 0;
11223}
11224
11225#endif
11226
11227#ifdef WIFI_HAL_VERSION_3
11228
developer1e5aa162022-09-13 16:06:24 +080011229INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11230{
11231 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11232 if (bitMap & WIFI_BITRATE_1MBPS)
11233 strcat(BasicRate, "1,");
11234 if (bitMap & WIFI_BITRATE_2MBPS)
11235 strcat(BasicRate, "2,");
11236 if (bitMap & WIFI_BITRATE_5_5MBPS)
11237 strcat(BasicRate, "5.5,");
11238 if (bitMap & WIFI_BITRATE_6MBPS)
11239 strcat(BasicRate, "6,");
11240 if (bitMap & WIFI_BITRATE_9MBPS)
11241 strcat(BasicRate, "9,");
11242 if (bitMap & WIFI_BITRATE_11MBPS)
11243 strcat(BasicRate, "11,");
11244 if (bitMap & WIFI_BITRATE_12MBPS)
11245 strcat(BasicRate, "12,");
11246 if (bitMap & WIFI_BITRATE_18MBPS)
11247 strcat(BasicRate, "18,");
11248 if (bitMap & WIFI_BITRATE_24MBPS)
11249 strcat(BasicRate, "24,");
11250 if (bitMap & WIFI_BITRATE_36MBPS)
11251 strcat(BasicRate, "36,");
11252 if (bitMap & WIFI_BITRATE_48MBPS)
11253 strcat(BasicRate, "48,");
11254 if (bitMap & WIFI_BITRATE_54MBPS)
11255 strcat(BasicRate, "54,");
11256 if (strlen(BasicRate) != 0) // remove last comma
11257 BasicRate[strlen(BasicRate) - 1] = '\0';
11258 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11259 return RETURN_OK;
11260}
11261
11262INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11263{
11264 UINT BitMap = 0;
11265 char *rate;
11266
11267 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11268 rate = strtok(BasicRatesList, ",");
11269 while(rate != NULL)
11270 {
11271 if (strcmp(rate, "1") == 0)
11272 BitMap |= WIFI_BITRATE_1MBPS;
11273 else if (strcmp(rate, "2") == 0)
11274 BitMap |= WIFI_BITRATE_2MBPS;
11275 else if (strcmp(rate, "5.5") == 0)
11276 BitMap |= WIFI_BITRATE_5_5MBPS;
11277 else if (strcmp(rate, "6") == 0)
11278 BitMap |= WIFI_BITRATE_6MBPS;
11279 else if (strcmp(rate, "9") == 0)
11280 BitMap |= WIFI_BITRATE_9MBPS;
11281 else if (strcmp(rate, "11") == 0)
11282 BitMap |= WIFI_BITRATE_11MBPS;
11283 else if (strcmp(rate, "12") == 0)
11284 BitMap |= WIFI_BITRATE_12MBPS;
11285 else if (strcmp(rate, "18") == 0)
11286 BitMap |= WIFI_BITRATE_18MBPS;
11287 else if (strcmp(rate, "24") == 0)
11288 BitMap |= WIFI_BITRATE_24MBPS;
11289 else if (strcmp(rate, "36") == 0)
11290 BitMap |= WIFI_BITRATE_36MBPS;
11291 else if (strcmp(rate, "48") == 0)
11292 BitMap |= WIFI_BITRATE_48MBPS;
11293 else if (strcmp(rate, "54") == 0)
11294 BitMap |= WIFI_BITRATE_54MBPS;
11295 rate = strtok(NULL, ",");
11296 }
11297 *basicRateBitMap = BitMap;
11298 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11299 return RETURN_OK;
11300}
11301
11302// 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 +080011303INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11304{
developer1e5aa162022-09-13 16:06:24 +080011305 char buf[128] = {0};
11306 char cmd[128] = {0};
11307 char config_file[64] = {0};
11308 int bandwidth;
11309 int set_mode;
11310 wifi_radio_operationParam_t current_param;
11311
11312 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11313
11314 multiple_set = TRUE;
11315 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11316 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11317 return RETURN_ERR;
11318 }
11319 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11320 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11321 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11322 return RETURN_ERR;
11323 }
11324 }
11325 if (current_param.channelWidth != operationParam->channelWidth || (current_param.channel != operationParam->channel && !operationParam->autoChannelEnabled)) {
11326 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11327 bandwidth = 20;
11328 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11329 bandwidth = 40;
11330 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11331 bandwidth = 80;
11332 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11333 bandwidth = 160;
11334 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11335 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11336 return RETURN_ERR;
11337 }
11338 }
11339 if (current_param.variant != operationParam->variant) {
11340 // Two different definition bit map, so need to check every bit.
11341 if (operationParam->variant & WIFI_80211_VARIANT_A)
11342 set_mode |= WIFI_MODE_A;
11343 if (operationParam->variant & WIFI_80211_VARIANT_B)
11344 set_mode |= WIFI_MODE_B;
11345 if (operationParam->variant & WIFI_80211_VARIANT_G)
11346 set_mode |= WIFI_MODE_G;
11347 if (operationParam->variant & WIFI_80211_VARIANT_N)
11348 set_mode |= WIFI_MODE_N;
11349 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11350 set_mode |= WIFI_MODE_AC;
11351 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11352 set_mode |= WIFI_MODE_AX;
11353 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11354 memset(buf, 0, sizeof(buf));
11355 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11356 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11357 return RETURN_ERR;
11358 }
11359 }
11360 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11361 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11362 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11363 return RETURN_ERR;
11364 }
11365 }
11366 if (current_param.beaconInterval != operationParam->beaconInterval) {
11367 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11368 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11369 return RETURN_ERR;
11370 }
11371 }
11372 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11373 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11374 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11375 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11376 return RETURN_ERR;
11377 }
11378 }
11379 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11380 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11381 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11382 return RETURN_ERR;
11383 }
11384 }
11385 if (current_param.guardInterval != operationParam->guardInterval) {
11386 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11387 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11388 return RETURN_ERR;
11389 }
11390 }
11391 if (current_param.transmitPower != operationParam->transmitPower) {
11392 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11393 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11394 return RETURN_ERR;
11395 }
11396 }
11397 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11398 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11399 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11400 return RETURN_ERR;
11401 }
11402 }
11403 if (current_param.obssCoex != operationParam->obssCoex) {
11404 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11405 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11406 return RETURN_ERR;
11407 }
11408 }
11409 if (current_param.stbcEnable != operationParam->stbcEnable) {
11410 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11411 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11412 return RETURN_ERR;
11413 }
11414 }
11415 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11416 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11417 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11418 return RETURN_ERR;
11419 }
11420 }
11421
11422 // if enable is true, then restart the radio
11423 wifi_setRadioEnable(index, FALSE);
11424 if (operationParam->enable == TRUE)
11425 wifi_setRadioEnable(index, TRUE);
11426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11427
developer06a01d92022-09-07 16:32:39 +080011428 return RETURN_OK;
11429}
11430
11431INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11432{
developer1e5aa162022-09-13 16:06:24 +080011433 char band[64] = {0};
11434 char buf[256] = {0};
11435 char config_file[64] = {0};
11436 char cmd[128] = {0};
11437 int ret = RETURN_ERR;
11438 int mode = 0;
11439 ULONG channel = 0;
11440 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011441
11442 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11443 printf("Entering %s index = %d\n", __func__, (int)index);
11444
developer1e5aa162022-09-13 16:06:24 +080011445 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11446 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11447 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011448 {
developer1e5aa162022-09-13 16:06:24 +080011449 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011450 return RETURN_ERR;
11451 }
11452 operationParam->enable = enabled;
11453
11454 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011455 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011456 {
developer1e5aa162022-09-13 16:06:24 +080011457 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011458 return RETURN_ERR;
11459 }
11460
11461 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011462 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011463 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011464 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011465 else if (!strcmp(band, "6GHz"))
11466 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011467 else
11468 {
developer1e5aa162022-09-13 16:06:24 +080011469 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011470 band);
11471 }
11472
developer1e5aa162022-09-13 16:06:24 +080011473 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11474 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11475 operationParam->channel = 0;
11476 operationParam->autoChannelEnabled = TRUE;
11477 } else {
11478 operationParam->channel = strtol(buf, NULL, 10);
11479 operationParam->autoChannelEnabled = FALSE;
11480 }
11481
developer06a01d92022-09-07 16:32:39 +080011482 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011483 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11484 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11485 return RETURN_ERR;
11486 }
developer06a01d92022-09-07 16:32:39 +080011487 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11488 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11489 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer1e5aa162022-09-13 16:06:24 +080011490 else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11491 else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011492 else
11493 {
developer1e5aa162022-09-13 16:06:24 +080011494 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11495 return false;
developer06a01d92022-09-07 16:32:39 +080011496 }
11497
developer1e5aa162022-09-13 16:06:24 +080011498 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11499 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11500 return RETURN_ERR;
11501 }
11502 // Two different definition bit map, so need to check every bit.
11503 if (mode & WIFI_MODE_A)
11504 operationParam->variant |= WIFI_80211_VARIANT_A;
11505 if (mode & WIFI_MODE_B)
11506 operationParam->variant |= WIFI_80211_VARIANT_B;
11507 if (mode & WIFI_MODE_G)
11508 operationParam->variant |= WIFI_80211_VARIANT_G;
11509 if (mode & WIFI_MODE_N)
11510 operationParam->variant |= WIFI_80211_VARIANT_N;
11511 if (mode & WIFI_MODE_AC)
11512 operationParam->variant |= WIFI_80211_VARIANT_AC;
11513 if (mode & WIFI_MODE_AX)
11514 operationParam->variant |= WIFI_80211_VARIANT_AX;
11515 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11516 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11517 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011518 }
developer1e5aa162022-09-13 16:06:24 +080011519 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11520 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11521 return RETURN_ERR;
11522 }
11523 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11524 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11525 return RETURN_ERR;
11526 }
developer06a01d92022-09-07 16:32:39 +080011527
developer1e5aa162022-09-13 16:06:24 +080011528 memset(buf, 0, sizeof(buf));
11529 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11530 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11531 return RETURN_ERR;
11532 }
11533 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11534
11535 memset(buf, 0, sizeof(buf));
11536 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11537 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11538 return RETURN_ERR;
11539 }
11540 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11541
11542 memset(buf, 0, sizeof(buf));
11543 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11544 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11545
11546 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11547 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11548 return RETURN_ERR;
11549 }
11550 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11551 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11552 return RETURN_ERR;
11553 }
11554
11555 memset(buf, 0, sizeof(buf));
11556 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11557 if (strcmp(buf, "-1") == 0) {
11558 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11559 operationParam->ctsProtection = FALSE;
11560 } else {
11561 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11562 operationParam->ctsProtection = TRUE;
11563 }
11564
11565 memset(buf, 0, sizeof(buf));
11566 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11567 if (strcmp(buf, "0") == 0)
11568 operationParam->obssCoex = FALSE;
11569 else
11570 operationParam->obssCoex = TRUE;
11571
11572 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11573 _syscmd(cmd, buf, sizeof(buf));
11574 if (strlen(buf) != 0)
11575 operationParam->stbcEnable = TRUE;
11576 else
11577 operationParam->stbcEnable = FALSE;
11578
11579 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11580 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11581 return RETURN_ERR;
11582 }
11583
11584 // Below value is hardcoded
11585
11586 operationParam->numSecondaryChannels = 0;
11587 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11588 operationParam->channelSecondary[i] = 0;
11589 }
11590 operationParam->csa_beacon_count = 15;
11591 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011592
11593 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11594 return RETURN_OK;
11595}
11596
11597static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11598{
11599 if (radioIndex != 0 && radioIndex != 1)
11600 {
11601 printf("%s: Wrong radio index (%d)\n", __func__, index);
11602 return -1;
11603 }
11604
11605 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
11606 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
11607
11608 return (arrayIndex * 2) + radioIndex;
11609}
11610
11611INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11612{
11613 INT ret;
11614 int i;
11615 BOOL enabled = false;
11616 char buf[256];
11617 wifi_secur_list *secur_item;
11618 int vap_index;
11619 INT mode;
11620 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
11621
11622 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11623 printf("Entering %s index = %d\n", __func__, (int)index);
11624
11625 map->vap_array[index].radio_index = index;
11626 for (i = 0; i < 5; i++)
11627 {
11628 vap_index = array_index_to_vap_index(index, i);
11629 if (vap_index < 0)
11630 {
11631 return RETURN_ERR;
11632 }
11633
11634 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
11635
11636 map->vap_array[i].vap_index = vap_index;
11637
11638 memset(buf, 0, sizeof(buf));
11639 wifi_getApName(vap_index, buf); // XXX: error handling
11640 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
11641
11642 ret = wifi_getSSIDEnable(vap_index, &enabled);
11643 if (ret != RETURN_OK)
11644 {
11645 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
11646 return RETURN_ERR;
11647 }
11648 map->vap_array[i].u.bss_info.enabled = enabled;
11649
11650 memset(buf, 0, sizeof(buf));
11651 wifi_getBaseBSSID(vap_index, buf);
11652 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11653 &map->vap_array[i].u.bss_info.bssid[0],
11654 &map->vap_array[i].u.bss_info.bssid[1],
11655 &map->vap_array[i].u.bss_info.bssid[2],
11656 &map->vap_array[i].u.bss_info.bssid[3],
11657 &map->vap_array[i].u.bss_info.bssid[4],
11658 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
11659
11660 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
11661 map->vap_array[i].u.bss_info.showSsid = enabled;
11662
11663 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
11664 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
11665 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
11666
11667 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11668 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
11669
11670 memset(buf, 0, sizeof(buf));
11671 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
11672 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
11673
11674 wifi_getApSecurityModeEnabled(vap_index, buf);
11675
11676 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
11677 {
11678 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
11679 return RETURN_ERR;
11680 }
11681 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
11682
11683 memset(buf, 0, sizeof(buf));
11684 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
11685 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);
11686
11687 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
11688 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
11689
11690 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
11691 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
11692
11693 wifi_getApIsolationEnable(vap_index, &enabled);
11694 map->vap_array[i].u.bss_info.isolation = enabled;
11695 }
11696 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11697 return RETURN_OK;
11698}
11699
11700INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11701{
11702 unsigned int i;
11703 wifi_vap_info_t *vap_info = NULL;
11704 int acl_mode;
11705 char *sec_str = NULL;
11706
11707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11708 printf("Entering %s index = %d\n", __func__, (int)index);
11709 for (i = 0; i < map->num_vaps; i++)
11710 {
11711 vap_info = &map->vap_array[i];
11712 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11713
11714 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11715 else
11716 {
11717 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11718 else acl_mode = 1;
11719 }
11720 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11721 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11722 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11723
11724 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11725 if (sec_str)
11726 {
11727 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11728 }
11729 else
11730 {
11731 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11732 }
11733
11734 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11735 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11736
11737 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11738 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11739
11740 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11741
11742 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11743 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11744 }
11745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11746 return RETURN_OK;
11747}
11748
11749int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11750{
11751 char *token, *next;
11752 const char s[2] = ",";
11753 int count =0;
11754
11755 /* get the first token */
11756 token = strtok_r(pchannels, s, &next);
11757
11758 /* walk through other tokens */
11759 while( token != NULL && count < MAX_CHANNELS) {
11760 chlistptr->channels_list[count++] = atoi(token);
11761 token = strtok_r(NULL, s, &next);
11762 }
11763
11764 return count;
11765}
11766
11767static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11768{
11769 INT status;
11770 wifi_channels_list_t *chlistp;
11771 CHAR output_string[64];
11772 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011773 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011774
11775 if(rcap == NULL)
11776 {
11777 return RETURN_ERR;
11778 }
11779
11780 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011781 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011782
developer1e5aa162022-09-13 16:06:24 +080011783 if (band == band_2_4)
11784 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11785 else if (band == band_5)
11786 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11787 else if (band == band_6)
11788 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011789
11790 chlistp = &(rcap->channel_list[0]);
11791 memset(pchannels, 0, sizeof(pchannels));
11792
11793 /* possible number of radio channels */
11794 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11795 {
11796 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11797 }
11798 /* Number of channels and list*/
11799 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11800
11801 /* autoChannelSupported */
11802 /* always ON with wifi_getRadioAutoChannelSupported */
11803 rcap->autoChannelSupported = TRUE;
11804
11805 /* DCSSupported */
11806 /* always ON with wifi_getRadioDCSSupported */
11807 rcap->DCSSupported = TRUE;
11808
11809 /* zeroDFSSupported - TBD */
11810 rcap->zeroDFSSupported = FALSE;
11811
11812 /* Supported Country List*/
11813 memset(output_string, 0, sizeof(output_string));
11814 status = wifi_getRadioCountryCode(radioIndex, output_string);
11815 if( status != 0 ) {
11816 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11817 return RETURN_ERR;
11818 } else {
11819 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11820 }
11821 if(!strcmp(output_string,"US")){
11822 rcap->countrySupported[0] = wifi_countrycode_US;
11823 rcap->countrySupported[1] = wifi_countrycode_CA;
11824 } else if (!strcmp(output_string,"CA")) {
11825 rcap->countrySupported[0] = wifi_countrycode_CA;
11826 rcap->countrySupported[1] = wifi_countrycode_US;
11827 } else {
11828 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11829 }
11830
11831 rcap->numcountrySupported = 2;
11832
11833 /* csi */
11834 rcap->csi.maxDevices = 8;
11835 rcap->csi.soudingFrameSupported = TRUE;
11836
11837 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
11838
11839 /* channelWidth - all supported bandwidths */
11840 int i=0;
11841 rcap->channelWidth[i] = 0;
11842 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11843 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11844 WIFI_CHANNELBANDWIDTH_40MHZ);
11845
11846 }
developer1e5aa162022-09-13 16:06:24 +080011847 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080011848 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11849 WIFI_CHANNELBANDWIDTH_40MHZ |
11850 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
11851 }
11852
11853
11854 /* mode - all supported variants */
11855 // rcap->mode[i] = WIFI_80211_VARIANT_H;
11856 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011857 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 +080011858 }
11859 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011860 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
11861 }
11862 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
11863 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011864 }
11865 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
11866 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
11867
11868 /* supportedBitRate - all supported bitrates */
11869 rcap->supportedBitRate[i] = 0;
11870 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11871 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11872 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
11873 }
developer1e5aa162022-09-13 16:06:24 +080011874 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080011875 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11876 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
11877 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
11878 }
11879
11880
11881 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
11882 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
11883 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
11884 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
11885 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
11886 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
11887 rcap->cipherSupported = 0;
11888 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
11889 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
11890
11891 return RETURN_OK;
11892}
11893
11894INT wifi_getHalCapability(wifi_hal_capability_t *cap)
11895{
11896 INT status, radioIndex;
11897 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
11898 int iter = 0;
11899 unsigned int j;
11900 wifi_interface_name_idex_map_t *iface_info;
11901
11902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11903
11904 memset(cap, 0, sizeof(wifi_hal_capability_t));
11905
11906 /* version */
11907 cap->version.major = WIFI_HAL_MAJOR_VERSION;
11908 cap->version.minor = WIFI_HAL_MINOR_VERSION;
11909
11910 /* number of radios platform property */
11911 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
11912 _syscmd(cmd, output, sizeof(output));
11913 cap->wifi_prop.numRadios = atoi(output);
11914
11915 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
11916 {
11917 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
11918 if (status != 0) {
11919 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
11920 return RETURN_ERR;
11921 }
11922
11923 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
11924 {
11925 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
11926 {
11927 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
11928 return RETURN_ERR;
11929 }
11930 iface_info = &cap->wifi_prop.interface_map[iter];
11931 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
11932 iface_info->rdk_radio_index = radioIndex;
11933 memset(output, 0, sizeof(output));
11934 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
11935 {
11936 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
11937 }
11938 // TODO: bridge name
11939 // TODO: vlan id
11940 // TODO: primary
11941 iface_info->index = array_index_to_vap_index(radioIndex, j);
11942 memset(output, 0, sizeof(output));
11943 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
11944 {
11945 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
11946 }
11947 iter++;
11948 }
11949 }
11950
11951 cap->BandSteeringSupported = FALSE;
11952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11953 return RETURN_OK;
11954}
11955
11956INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
11957{
developer587c1b62022-09-27 15:58:59 +080011958 char buf[128] = {0};
11959 char config_file[128] = {0};
11960 char password[64] = {0};
11961 char mfp[32] = {0};
11962 char wpa_mode[32] = {0};
11963 struct params params = {0};
11964
11965 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11966
11967 multiple_set = TRUE;
11968 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11969 if (security->mode == wifi_security_mode_none) {
11970 strcpy(wpa_mode, "None");
11971 } else if (security->mode == wifi_security_mode_wpa_personal)
11972 strcpy(wpa_mode, "WPA-Personal");
11973 else if (security->mode == wifi_security_mode_wpa2_personal)
11974 strcpy(wpa_mode, "WPA2-Personal");
11975 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
11976 strcpy(wpa_mode, "WPA-WPA2-Personal");
11977 else if (security->mode == wifi_security_mode_wpa_enterprise)
11978 strcpy(wpa_mode, "WPA-Enterprise");
11979 else if (security->mode == wifi_security_mode_wpa2_enterprise)
11980 strcpy(wpa_mode, "WPA2-Enterprise");
11981 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
11982 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
11983 else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
11984 strcpy(wpa_mode, "WPA3-Personal");
11985 else if (security->mode == wifi_security_mode_wpa3_enterprise)
11986 strcpy(wpa_mode, "WPA3-Enterprise");
11987
11988 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
11989
11990 strncpy(password, security->u.key.key, 63);
11991 password[63] = '\0';
11992 wifi_setApSecurityKeyPassphrase(ap_index, password);
11993
11994 if (security->mode != wifi_security_mode_none) {
11995 memset(&params, 0, sizeof(params));
11996 params.name = "wpa_pairwise";
11997 if (security->encr == wifi_encryption_tkip)
11998 params.value = "TKIP";
11999 else if (security->encr == wifi_encryption_aes)
12000 params.value = "CCMP";
12001 else if (security->encr == wifi_encryption_aes_tkip)
12002 params.value = "TKIP CCMP";
12003 wifi_hostapdWrite(config_file, &params, 1);
12004 }
12005
12006 if (security->mfp == wifi_mfp_cfg_disabled)
12007 strcpy(mfp, "Disable");
12008 else if (security->mfp == wifi_mfp_cfg_optional)
12009 strcpy(mfp, "Optional");
12010 else if (security->mfp == wifi_mfp_cfg_required)
12011 strcpy(mfp, "Required");
12012 wifi_setApSecurityMFPConfig(ap_index, mfp);
12013
12014 memset(&params, 0, sizeof(params));
12015 params.name = "transition_disable";
12016 if (security->wpa3_transition_disable == TRUE)
12017 params.value = "0x01";
12018 else
12019 params.value = "0x00";
12020 wifi_hostapdWrite(config_file, &params, 1);
12021
12022 memset(&params, 0, sizeof(params));
12023 params.name = "wpa_group_rekey";
12024 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12025 params.value = buf;
12026 wifi_hostapdWrite(config_file, &params, 1);
12027
12028 memset(&params, 0, sizeof(params));
12029 params.name = "wpa_strict_rekey";
12030 params.value = security->strict_rekey?"1":"0";
12031 wifi_hostapdWrite(config_file, &params, 1);
12032
12033 memset(&params, 0, sizeof(params));
12034 params.name = "wpa_pairwise_update_count";
12035 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12036 params.value = buf;
12037 wifi_hostapdWrite(config_file, &params, 1);
12038
12039 memset(&params, 0, sizeof(params));
12040 params.name = "disable_pmksa_caching";
12041 params.value = security->disable_pmksa_caching?"1":"0";
12042 wifi_hostapdWrite(config_file, &params, 1);
12043
12044 wifi_setApEnable(ap_index, FALSE);
12045 wifi_setApEnable(ap_index, TRUE);
12046
12047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12048
developer06a01d92022-09-07 16:32:39 +080012049 return RETURN_OK;
12050}
12051
12052INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12053{
developer587c1b62022-09-27 15:58:59 +080012054 char buf[128] = {0};
12055 char config_file[128] = {0};
12056 int disable = 0;
12057 // struct params params = {0};
12058
12059 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12060 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12061 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12062 security->mode = wifi_security_mode_none;
12063 if (strlen(buf) != 0) {
12064 if (strcmp(buf, "WPA-Personal"))
12065 security->mode = wifi_security_mode_wpa_personal;
12066 else if (strcmp(buf, "WPA2-Personal"))
12067 security->mode = wifi_security_mode_wpa2_personal;
12068 else if (strcmp(buf, "WPA-WPA2-Personal"))
12069 security->mode = wifi_security_mode_wpa_wpa2_personal;
12070 else if (strcmp(buf, "WPA-Enterprise"))
12071 security->mode = wifi_security_mode_wpa_enterprise;
12072 else if (strcmp(buf, "WPA2-Enterprise"))
12073 security->mode = wifi_security_mode_wpa2_enterprise;
12074 else if (strcmp(buf, "WPA-WPA2-Enterprise"))
12075 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
12076 else if (strcmp(buf, "WPA3-Personal"))
12077 security->mode = wifi_security_mode_wpa3_personal;
12078 else if (strcmp(buf, "WPA3-Transition"))
12079 security->mode = wifi_security_mode_wpa3_transition;
12080 else if (strcmp(buf, "WPA3-Enterprise"))
12081 security->mode = wifi_security_mode_wpa3_enterprise;
12082 }
12083
12084 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12085 if (security->mode == wifi_security_mode_none)
12086 security->encr = wifi_encryption_none;
12087 else {
12088 if (strcmp(buf, "TKIP") == 0)
12089 security->encr = wifi_encryption_tkip;
12090 else if (strcmp(buf, "CCMP") == 0)
12091 security->encr = wifi_encryption_aes;
12092 else
12093 security->encr = wifi_encryption_aes_tkip;
12094 }
12095
12096 memset(buf, 0, sizeof(buf));
12097 wifi_getApSecurityMFPConfig(ap_index, buf);
12098 if (strcmp(buf, "Disabled") == 0)
12099 security->mfp = wifi_mfp_cfg_disabled;
12100 else if (strcmp(buf, "Optional") == 0)
12101 security->mfp = wifi_mfp_cfg_optional;
12102 else if (strcmp(buf, "Required") == 0)
12103 security->mfp = wifi_mfp_cfg_required;
12104
12105 memset(buf, 0, sizeof(buf));
12106 security->wpa3_transition_disable = FALSE;
12107 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12108 disable = strtol(buf, NULL, 16);
12109 if (disable != 0)
12110 security->wpa3_transition_disable = TRUE;
12111
12112 memset(buf, 0, sizeof(buf));
12113 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12114 if (strlen(buf) == 0)
12115 security->rekey_interval = 86400;
12116 else
12117 security->rekey_interval = strtol(buf, NULL, 10);
12118
12119 memset(buf, 0, sizeof(buf));
12120 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12121 if (strlen(buf) == 0)
12122 security->strict_rekey = 1;
12123 else
12124 security->strict_rekey = strtol(buf, NULL, 10);
12125
12126 memset(buf, 0, sizeof(buf));
12127 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12128 if (strlen(buf) == 0)
12129 security->eapol_key_retries = 4;
12130 else
12131 security->eapol_key_retries = strtol(buf, NULL, 10);
12132
12133 memset(buf, 0, sizeof(buf));
12134 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12135 if (strlen(buf) == 0)
12136 security->disable_pmksa_caching = FALSE;
12137 else
12138 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12139
12140 /* TODO
12141 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12142 */
12143 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12144 security->eap_identity_req_timeout = 0;
12145 security->eap_identity_req_retries = 0;
12146 security->eap_req_timeout = 0;
12147 security->eap_req_retries = 0;
12148 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012149 return RETURN_OK;
12150}
12151
12152#endif /* WIFI_HAL_VERSION_3 */
12153
12154#ifdef WIFI_HAL_VERSION_3_PHASE2
12155INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12156{
developer13df9332022-09-27 16:53:22 +080012157 char cmd[128] = {0};
12158 char buf[128] = {0};
12159 char *mac_addr = NULL;
12160 BOOL status = FALSE;
12161 size_t len = 0;
12162
12163 if(ap_index > MAX_APS)
12164 return RETURN_ERR;
12165
12166 *output_numDevices = 0;
12167 wifi_getApEnable(ap_index, &status);
12168 if (status == FALSE)
12169 return RETURN_OK;
12170
12171 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12172 _syscmd(cmd, buf, sizeof(buf));
12173
12174 mac_addr = strtok(buf, "\n");
12175 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12176 *output_numDevices = i + 1;
12177 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12178 addr_ptr = output_deviceMacAddressArray[i];
12179 mac_addr_aton(addr_ptr, mac_addr);
12180 mac_addr = strtok(NULL, "\n");
12181 }
12182
12183 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012184}
12185#else
12186INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12187{
12188 char cmd[128];
12189 BOOL status = false;
12190
12191 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12192 return RETURN_ERR;
12193
12194 output_buf[0] = '\0';
12195
12196 wifi_getApEnable(ap_index,&status);
12197 if (!status)
12198 return RETURN_OK;
12199
12200 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12201 _syscmd(cmd, output_buf, output_buf_size);
12202
12203 return RETURN_OK;
12204}
12205#endif
developer2f513ab2022-09-13 14:26:06 +080012206
12207INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12208{
12209 char output[16]={'\0'};
12210 char config_file[MAX_BUF_SIZE] = {0};
12211
12212 if (!enable)
12213 return RETURN_ERR;
12214
12215 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12216 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12217
12218 if (strlen(output) == 0)
12219 *enable = FALSE;
12220 else if (strncmp(output, "1", 1) == 0)
12221 *enable = TRUE;
12222 else
12223 *enable = FALSE;
12224
12225 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12226 return RETURN_OK;
12227}
developer2d9c30f2022-09-13 15:06:14 +080012228
12229INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12230{
12231 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12232 return RETURN_ERR;
12233 *output_enable=TRUE;
12234 return RETURN_OK;
12235}
developerfd7d2892022-09-13 16:44:53 +080012236
12237INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12238{
12239 char cmd[128] = {0};
12240 char buf[128] = {0};
12241 char line[128] = {0};
12242 size_t len = 0;
12243 ssize_t read = 0;
12244 FILE *f = NULL;
12245 int index = 0;
12246 int exp = 0;
12247 int mantissa = 0;
12248 int duration = 0;
12249 int radio_index = 0;
12250 int max_radio_num = 0;
12251 uint twt_wake_interval = 0;
12252
12253 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12254
12255 wifi_getMaxRadioNumber(&max_radio_num);
12256 radio_index = ap_index % max_radio_num;
12257 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12258 _syscmd(cmd, buf, sizeof(buf));
12259 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12260 if (*numSessionReturned > maxNumberSessions)
12261 *numSessionReturned = maxNumberSessions;
12262 else if (*numSessionReturned < 1) {
12263 *numSessionReturned = 0;
12264 return RETURN_OK;
12265 }
12266
12267 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12268 if ((f = popen(cmd, "r")) == NULL) {
12269 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12270 return RETURN_ERR;
12271 }
12272
12273 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12274 while((read = fgets(line, sizeof(line), f)) != NULL) {
12275 char *tmp = NULL;
12276 strcpy(buf, line);
12277 tmp = strtok(buf, " ");
12278 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12279 tmp = strtok(NULL, " ");
12280 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12281 tmp = strtok(NULL, " ");
12282 if (strstr(tmp, "t")) {
12283 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12284 }
12285 if (strstr(tmp, "a")) {
12286 twtSessions[index].twtParameters.operation.announced = TRUE;
12287 }
12288 tmp = strtok(NULL, " ");
12289 exp = strtol(tmp, NULL, 10);
12290 tmp = strtok(NULL, " ");
12291 mantissa = strtol(tmp, NULL, 10);
12292 tmp = strtok(NULL, " ");
12293 duration = strtol(tmp, NULL, 10);
12294
12295 // only implicit supported
12296 twtSessions[index].twtParameters.operation.implicit = TRUE;
12297 // only individual agreement supported
12298 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12299
12300 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12301 twt_wake_interval = mantissa * (1 << exp);
12302 if (twt_wake_interval/mantissa != (1 << exp)) {
12303 // Overflow handling
12304 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12305 } else {
12306 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12307 }
12308 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12309 index++;
12310 }
12311
12312 pclose(f);
12313 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12314 return RETURN_OK;
12315}