blob: 2d814e670b68b61be92cbce5b589a41f3fddfe2e [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>
developerefb790a2023-12-26 18:58:32 +080064#include <pthread.h>
65
developer06a01d92022-09-07 16:32:39 +080066#define MAC_ALEN 6
67
developer7930d352022-12-21 17:55:42 +080068#define MAX_BUF_SIZE 256
69#define MAX_CMD_SIZE 256
70#define IF_NAME_SIZE 16
developer06a01d92022-09-07 16:32:39 +080071#define CONFIG_PREFIX "/nvram/hostapd"
developer431128d2022-12-16 15:30:41 +080072#define ACL_PREFIX "/nvram/hostapd-acl"
73#define DENY_PREFIX "/nvram/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080074//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
75#define SOCK_PREFIX "/var/run/hostapd/wifi"
developer431128d2022-12-16 15:30:41 +080076#define VAP_STATUS_FILE "/nvram/vap-status"
developera3c68b92022-09-13 15:27:29 +080077#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080078#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080079#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080080#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080081#define VLAN_FILE "/nvram/hostapd.vlan"
developer431128d2022-12-16 15:30:41 +080082#define PSK_FILE "/nvram/hostapd"
developerf49437e2022-09-29 19:58:21 +080083#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080084#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080085
developer81bf2ed2022-09-13 15:31:14 +080086#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080087
88/*
89 MAX_APS - Number of all AP available in system
90 2x Home AP
91 2x Backhaul AP
92 2x Guest AP
93 2x Secure Onboard AP
94 2x Service AP
95
96*/
developer06a01d92022-09-07 16:32:39 +080097
developer033b37b2022-10-18 11:27:46 +080098
developera77d84b2023-02-22 16:10:50 +080099#define MAX_APS ((MAX_NUM_RADIOS)*(MAX_NUM_VAP_PER_RADIO))
developer06a01d92022-09-07 16:32:39 +0800100#ifndef AP_PREFIX
101#define AP_PREFIX "wifi"
102#endif
103
104#ifndef RADIO_PREFIX
105#define RADIO_PREFIX "wlan"
106#endif
107
developer89df4502023-02-16 20:45:02 +0800108#define MAX_ASSOCIATED_STA_NUM 2007 // hostapd default
developer06a01d92022-09-07 16:32:39 +0800109
110//Uncomment to enable debug logs
111//#define WIFI_DEBUG
112
113#ifdef WIFI_DEBUG
114#define wifi_dbg_printf printf
115#define WIFI_ENTRY_EXIT_DEBUG printf
116#else
117#define wifi_dbg_printf(format, args...) printf("")
118#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
119#endif
120
121#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
122#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
123#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
124#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
125#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
126#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
127#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
128#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
129#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
130#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
131
developer4fb0b922022-09-30 14:29:09 +0800132#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800133
134#define BW_FNAME "/nvram/bw_file.txt"
135
136#define PS_MAX_TID 16
137
developer439baa32024-05-02 15:54:58 +0800138
139#ifdef SINGLE_WIPHY_SUPPORT
140#define single_wiphy TRUE
141#else
142#define single_wiphy FALSE
143#endif
144
developer06a01d92022-09-07 16:32:39 +0800145static 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,
developer7c4cd202023-03-01 10:56:29 +0800182 WIFI_MODE_BE = 0x40,
developerdb744382022-09-13 15:34:54 +0800183} wifi_ieee80211_Mode;
184
developer06a01d92022-09-07 16:32:39 +0800185#ifdef WIFI_HAL_VERSION_3
186
187// Return number of elements in array
188#ifndef ARRAY_SIZE
189#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
190#endif /* ARRAY_SIZE */
191
192#ifndef ARRAY_AND_SIZE
193#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
194#endif /* ARRAY_AND_SIZE */
195
196#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
197
198typedef struct {
199 int32_t value;
200 int32_t param;
201 intptr_t key;
202 intptr_t data;
203} wifi_secur_list;
204
developerfa41b1f2023-01-06 10:25:51 +0800205static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
206static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
developer72ec5572023-01-05 16:27:13 +0800207static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer06a01d92022-09-07 16:32:39 +0800208wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
209wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
210char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800211static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800212
213static wifi_secur_list map_security[] =
214{
215 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
216 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
217 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
219 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
220 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
221 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
222 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800223 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
224 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800225 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800226 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800227};
228
developerefb790a2023-12-26 18:58:32 +0800229typedef struct {
230 char ssid[MAX_BUF_SIZE];
231 char wpa[MAX_BUF_SIZE];
232 char wpa_key_mgmt[MAX_BUF_SIZE];
233 char wpa_passphrase[MAX_BUF_SIZE];
234 char ap_isolate[MAX_BUF_SIZE];
235 char macaddr_acl[MAX_BUF_SIZE];
236 char bss_transition[MAX_BUF_SIZE];
237 char ignore_broadcast_ssid[MAX_BUF_SIZE];
238 char max_sta[MAX_BUF_SIZE];
239} __attribute__((packed)) wifi_vap_cfg_t;
240
241pthread_t pthread_id;
242int result = 0, tflag = 0;
243wifi_vap_cfg_t vap_info[MAX_NUM_RADIOS*MAX_NUM_VAP_PER_RADIO];
244int syn_flag = 0;
245
developer06a01d92022-09-07 16:32:39 +0800246wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
247{
248 wifi_secur_list *item;
249 int i;
250
251 for (item = list,i = 0;i < list_sz; item++, i++) {
252 if ((int)(item->key) == key) {
253 return item;
254 }
255 }
256
257 return NULL;
258}
259
260char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
261{
262 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
263
264 if (!item) {
265 return "";
266 }
267
268 return (char *)(item->data);
269}
270
271wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
272{
273 wifi_secur_list *item;
274 int i;
275
276 for (item = list,i = 0;i < list_sz; item++, i++) {
277 if (strcmp((char *)(item->data), str) == 0) {
278 return item;
279 }
280 }
281
282 return NULL;
283}
284#endif /* WIFI_HAL_VERSION_3 */
285
286#ifdef HAL_NETLINK_IMPL
287typedef struct {
288 int id;
289 struct nl_sock* socket;
290 struct nl_cb* cb;
291} Netlink;
292
293static int mac_addr_aton(unsigned char *mac_addr, char *arg)
294{
295 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800296 sscanf(arg, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
developer06a01d92022-09-07 16:32:39 +0800297 mac_addr[0] = mac_addr_int[0];
298 mac_addr[1] = mac_addr_int[1];
299 mac_addr[2] = mac_addr_int[2];
300 mac_addr[3] = mac_addr_int[3];
301 mac_addr[4] = mac_addr_int[4];
302 mac_addr[5] = mac_addr_int[5];
303 return 0;
304}
305
306static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
307{
308 unsigned int mac_addr_int[6]={};
309 mac_addr_int[0] = arg[0];
310 mac_addr_int[1] = arg[1];
311 mac_addr_int[2] = arg[2];
312 mac_addr_int[3] = arg[3];
313 mac_addr_int[4] = arg[4];
314 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800315 snprintf(mac_addr, 20, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
developer06a01d92022-09-07 16:32:39 +0800316 return;
317}
318
319static int ieee80211_frequency_to_channel(int freq)
320{
developerf5745ee2022-10-05 16:09:53 +0800321 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800322 if (freq == 2484)
323 return 14;
developerf5745ee2022-10-05 16:09:53 +0800324 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
325 else if (freq == 5935)
326 return 2;
developer06a01d92022-09-07 16:32:39 +0800327 else if (freq < 2484)
328 return (freq - 2407) / 5;
329 else if (freq >= 4910 && freq <= 4980)
330 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800331 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800332 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800333 else if (freq <= 45000) /* DMG band lower limit */
334 /* see 802.11ax D6.1 27.3.23.2 */
335 return (freq - 5950) / 5;
336 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800337 return (freq - 56160) / 2160;
338 else
339 return 0;
340}
341
342static int initSock80211(Netlink* nl) {
343 nl->socket = nl_socket_alloc();
344 if (!nl->socket) {
345 fprintf(stderr, "Failing to allocate the sock\n");
346 return -ENOMEM;
347 }
348
349 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
350
351 if (genl_connect(nl->socket)) {
352 fprintf(stderr, "Failed to connect\n");
353 nl_close(nl->socket);
354 nl_socket_free(nl->socket);
355 return -ENOLINK;
356 }
357
358 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
359 if (nl->id< 0) {
360 fprintf(stderr, "interface not found.\n");
361 nl_close(nl->socket);
362 nl_socket_free(nl->socket);
363 return -ENOENT;
364 }
365
366 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
367 if ((!nl->cb)) {
368 fprintf(stderr, "Failed to allocate netlink callback.\n");
369 nl_close(nl->socket);
370 nl_socket_free(nl->socket);
371 return ENOMEM;
372 }
373
374 return nl->id;
375}
376
377static int nlfree(Netlink *nl)
378{
379 nl_cb_put(nl->cb);
380 nl_close(nl->socket);
381 nl_socket_free(nl->socket);
382 return 0;
383}
384
385static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
386 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
387 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
388 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
389};
390
391static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
392};
393
394static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
395};
396
397typedef struct _wifi_channelStats_loc {
398 INT array_size;
399 INT ch_number;
400 BOOL ch_in_pool;
401 INT ch_noise;
402 BOOL ch_radar_noise;
403 INT ch_max_80211_rssi;
404 INT ch_non_80211_noise;
405 INT ch_utilization;
406 ULLONG ch_utilization_total;
407 ULLONG ch_utilization_busy;
408 ULLONG ch_utilization_busy_tx;
409 ULLONG ch_utilization_busy_rx;
410 ULLONG ch_utilization_busy_self;
411 ULLONG ch_utilization_busy_ext;
412} wifi_channelStats_t_loc;
413
414typedef struct wifi_device_info {
415 INT wifi_devIndex;
416 UCHAR wifi_devMacAddress[6];
417 CHAR wifi_devIPAddress[64];
418 BOOL wifi_devAssociatedDeviceAuthentiationState;
419 INT wifi_devSignalStrength;
420 INT wifi_devTxRate;
421 INT wifi_devRxRate;
422} wifi_device_info_t;
423
424#endif
425
426//For 5g Alias Interfaces
427static BOOL priv_flag = TRUE;
428static BOOL pub_flag = TRUE;
429static BOOL Radio_flag = TRUE;
430//wifi_setApBeaconRate(1, beaconRate);
431
developer1e5aa162022-09-13 16:06:24 +0800432BOOL multiple_set = FALSE;
433
developer06a01d92022-09-07 16:32:39 +0800434struct params
435{
436 char * name;
437 char * value;
438};
439
440static int _syscmd(char *cmd, char *retBuf, int retBufSize)
441{
442 FILE *f;
443 char *ptr = retBuf;
444 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
445
446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
447 if((f = popen(cmd, "r")) == NULL) {
448 fprintf(stderr,"\npopen %s error\n", cmd);
449 return RETURN_ERR;
450 }
451
452 while(!feof(f))
453 {
454 *ptr = 0;
455 if(bufSize>=128) {
456 bufbytes=128;
457 } else {
458 bufbytes=bufSize-1;
459 }
460
461 fgets(ptr,bufbytes,f);
462 readbytes=strlen(ptr);
463
464 if(!readbytes)
465 break;
466
467 bufSize-=readbytes;
468 ptr += readbytes;
469 }
470 cmd_ret = pclose(f);
471 retBuf[retBufSize-1]=0;
472 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
473
474 return cmd_ret >> 8;
475}
476
developer033b37b2022-10-18 11:27:46 +0800477INT radio_index_to_phy(int radioIndex)
478{
479 char cmd[128] = {0};
480 char buf[64] = {0};
481 int phyIndex = 0;
482 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
483 _syscmd(cmd, buf, sizeof(buf));
484
485 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800486 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800487 return RETURN_ERR;
488 }
489 sscanf(buf, "phy%d", &phyIndex);
490
491 return phyIndex;
492}
developer026ac9e2022-11-07 13:46:24 +0800493
developer431128d2022-12-16 15:30:41 +0800494INT wifi_getMaxRadioNumber(INT *max_radio_num)
495{
496 char cmd[64] = {0};
497 char buf[4] = {0};
498
499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
500
developer439baa32024-05-02 15:54:58 +0800501 snprintf(cmd, sizeof(cmd), "ls /sys/class/ieee80211 | wc -l");
developer431128d2022-12-16 15:30:41 +0800502 _syscmd(cmd, buf, sizeof(buf));
503 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
504
505 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
506
507 return RETURN_OK;
508}
509
developer59ff6de2023-02-08 17:58:14 +0800510static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
511{
512 char cmd[MAX_CMD_SIZE]={'\0'};
513 char buf[MAX_BUF_SIZE]={'\0'};
514 int ret = 0;
515
516 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
517 ret = _syscmd(cmd, buf, sizeof(buf));
518 if ((ret != 0) && (strlen(buf) == 0))
519 return -1;
520 snprintf(output, output_size, "%s", buf);
521
522 return 0;
523}
524
525static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
526{
527 char cmd[MAX_CMD_SIZE]={'\0'};
528 char buf[MAX_BUF_SIZE]={'\0'};
529
530 for(int i=0;i<item_count;i++)
531 {
532 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
533 if (strlen(buf) == 0) //Insert
534 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
535 else //Update
536 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
537
538 if(_syscmd(cmd, buf, sizeof(buf)))
539 return -1;
540 }
541
542 return 0;
543}
544
developer431128d2022-12-16 15:30:41 +0800545wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800546{
547 char cmd[128] = {0};
548 char buf[64] = {0};
developer59ff6de2023-02-08 17:58:14 +0800549 char config_file[128] = {0};
developer026ac9e2022-11-07 13:46:24 +0800550 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800551 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800552 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800553 int radioIndex = 0;
554 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800555 wifi_band band = band_invalid;
556
557 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800558
developer431128d2022-12-16 15:30:41 +0800559 wifi_getMaxRadioNumber(&max_radio_num);
560 radioIndex = apIndex % max_radio_num;
developer439baa32024-05-02 15:54:58 +0800561 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
562 wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf));
563 if (strlen(buf) > 0)
564 return band_6;
developer5884e982022-10-06 10:52:50 +0800565
developer439baa32024-05-02 15:54:58 +0800566 memset(buf, 0, sizeof(buf));
567 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
568 if (strncmp(buf, "a", 1) == 0)
569 return band_5;
570 else
571 return band_2_4;
developerc707e972022-09-13 15:38:02 +0800572
573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
574 return band;
575}
576
developerd946fd62022-12-08 18:03:28 +0800577//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800578static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800579{
580 char config_file[128] = {0};
581
582 if (interface_name == NULL)
583 return RETURN_ERR;
584
585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerefb790a2023-12-26 18:58:32 +0800586#ifdef DYNAMIC_IF_NAME
developerd946fd62022-12-08 18:03:28 +0800587 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
588 wifi_hostapdRead(config_file, "interface", interface_name, 16);
589 if (strlen(interface_name) == 0)
590 return RETURN_ERR;
developerefb790a2023-12-26 18:58:32 +0800591#else
592 sprintf(interface_name, "%s%d",AP_PREFIX, apIndex);
593#endif
developerd946fd62022-12-08 18:03:28 +0800594 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
595 return RETURN_OK;
596}
597
developerac6f1142022-12-20 19:26:35 +0800598// wifi agent will call this function, do not change the parameter
599void GetInterfaceName(char *interface_name, char *conf_file)
600{
601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
602 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
603 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
604}
605
developer06a01d92022-09-07 16:32:39 +0800606static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
607{
developerd946fd62022-12-08 18:03:28 +0800608 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800609 if (multiple_set == TRUE)
610 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800611 char cmd[MAX_CMD_SIZE]="", output[32]="";
612 FILE *fp;
613 int i;
614 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800615 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800616 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800617 for(i=0; i<item_count; i++, list++)
618 {
developerd946fd62022-12-08 18:03:28 +0800619 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800620 if((fp = popen(cmd, "r"))==NULL)
621 {
622 perror("popen failed");
623 return -1;
624 }
625 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
626 {
627 pclose(fp);
628 perror("fgets failed");
629 return -1;
630 }
631 pclose(fp);
632 }
633 return 0;
634}
635
636static int wifi_reloadAp(int apIndex)
637{
developerd946fd62022-12-08 18:03:28 +0800638 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800639 if (multiple_set == TRUE)
640 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800641 char cmd[MAX_CMD_SIZE]="";
642 char buf[MAX_BUF_SIZE]="";
643
developerac6f1142022-12-20 19:26:35 +0800644 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800645 return RETURN_ERR;
646 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800647 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
648 return RETURN_ERR;
649
developerd946fd62022-12-08 18:03:28 +0800650 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800651 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
652 return RETURN_ERR;
653
developerd946fd62022-12-08 18:03:28 +0800654 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800655 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
656 return RETURN_ERR;
657
658 return RETURN_OK;
659}
660
developer06a01d92022-09-07 16:32:39 +0800661INT File_Reading(CHAR *file, char *Value)
662{
663 FILE *fp = NULL;
664 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
665 int count = 0;
666
667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
668 fp = popen(file,"r");
669 if(fp == NULL)
670 return RETURN_ERR;
671
672 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
673 {
674 for(count=0;buf[count]!='\n';count++)
675 copy_buf[count]=buf[count];
676 copy_buf[count]='\0';
677 }
678 strcpy(Value,copy_buf);
679 pclose(fp);
680 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
681
682 return RETURN_OK;
683}
684
685void wifi_RestartHostapd_2G()
686{
687 int Public2GApIndex = 4;
688
689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
690 wifi_setApEnable(Public2GApIndex, FALSE);
691 wifi_setApEnable(Public2GApIndex, TRUE);
692 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
693}
694
695void wifi_RestartHostapd_5G()
696{
697 int Public5GApIndex = 5;
698
699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
700 wifi_setApEnable(Public5GApIndex, FALSE);
701 wifi_setApEnable(Public5GApIndex, TRUE);
702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
703}
704
705void wifi_RestartPrivateWifi_2G()
706{
707 int PrivateApIndex = 0;
708
709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
710 wifi_setApEnable(PrivateApIndex, FALSE);
711 wifi_setApEnable(PrivateApIndex, TRUE);
712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
713}
714
715void wifi_RestartPrivateWifi_5G()
716{
717 int Private5GApIndex = 1;
718
719 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
720 wifi_setApEnable(Private5GApIndex, FALSE);
721 wifi_setApEnable(Private5GApIndex, TRUE);
722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
723}
724
725static int writeBandWidth(int radioIndex,char *bw_value)
726{
727 char buf[MAX_BUF_SIZE];
728 char cmd[MAX_CMD_SIZE];
729
730 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
731 if(_syscmd(cmd, buf, sizeof(buf)))
732 {
733 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
734 _syscmd(cmd, buf, sizeof(buf));
735 return RETURN_OK;
736 }
737
738 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
739 _syscmd(cmd,buf,sizeof(buf));
740 return RETURN_OK;
741}
742
743static int readBandWidth(int radioIndex,char *bw_value)
744{
developer30423732022-12-01 16:17:49 +0800745 char buf[MAX_BUF_SIZE] = {0};
746 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800747 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
748 _syscmd(cmd,buf,sizeof(buf));
749 if(NULL!=strstr(buf,"20MHz"))
developer06a01d92022-09-07 16:32:39 +0800750 strcpy(bw_value,"20MHz");
developer06a01d92022-09-07 16:32:39 +0800751 else if(NULL!=strstr(buf,"40MHz"))
developer06a01d92022-09-07 16:32:39 +0800752 strcpy(bw_value,"40MHz");
developer06a01d92022-09-07 16:32:39 +0800753 else if(NULL!=strstr(buf,"80MHz"))
developer06a01d92022-09-07 16:32:39 +0800754 strcpy(bw_value,"80MHz");
developer57fa24a2023-03-15 17:25:07 +0800755 else if(NULL!=strstr(buf,"160MHz"))
756 strcpy(bw_value,"160MHz");
757 else if(NULL!=strstr(buf,"320MHz"))
758 strcpy(bw_value,"320MHz");
developer06a01d92022-09-07 16:32:39 +0800759 else
developer06a01d92022-09-07 16:32:39 +0800760 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800761 return RETURN_OK;
762}
763
developer264159b2022-11-02 09:41:35 +0800764// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800765INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
766{
developer5f222492022-09-13 15:21:52 +0800767 struct params params={'\0'};
768 char config_file[MAX_BUF_SIZE] = {0};
769 char buf[MAX_BUF_SIZE] = {'\0'};
770
771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800772 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800773 if (strlen (beaconRate) >= 5) {
774 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
775 buf[strlen(beaconRate) - 4] = '\0';
776 } else if (strlen(beaconRate) > 0)
777 strcpy(buf, beaconRate);
778 else
779 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800780
781 params.name = "beacon_rate";
782 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
783 if (strncmp(buf, "5.5", 3) == 0) {
784 snprintf(buf, sizeof(buf), "55");
785 params.value = buf;
786 } else {
787 strcat(buf, "0");
788 params.value = buf;
789 }
790
791 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
792 wifi_hostapdWrite(config_file, &params, 1);
793 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
794 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
795
796 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800797}
798
799INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
800{
developer1d57d002022-10-12 18:03:15 +0800801 char config_file[128] = {'\0'};
802 char temp_output[128] = {'\0'};
803 char buf[128] = {'\0'};
804 char cmd[128] = {'\0'};
805 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800806 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800807
808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
809 if (NULL == beaconRate)
810 return RETURN_ERR;
811
812 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
813 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800814 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800815 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
816 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800817 if (strncmp(buf, "55", 2) == 0)
818 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
819 else {
820 rate = strtol(buf, NULL, 10)/10;
821 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
822 }
developer5f222492022-09-13 15:21:52 +0800823 } else {
developer1d57d002022-10-12 18:03:15 +0800824 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800825 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
developer1d57d002022-10-12 18:03:15 +0800826 _syscmd(cmd, buf, sizeof(buf));
827 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800828 }
829 strncpy(beaconRate, temp_output, sizeof(temp_output));
830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
831
832 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800833}
834
835INT wifi_setLED(INT radioIndex, BOOL enable)
836{
837 return 0;
838}
839INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
840{
841 return RETURN_OK;
842}
843/**********************************************************************************
844 *
845 * Wifi Subsystem level function prototypes
846 *
847**********************************************************************************/
848//---------------------------------------------------------------------------------------------------
849//Wifi system api
850//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
851INT wifi_getHalVersion(CHAR *output_string) //RDKB
852{
853 if(!output_string)
854 return RETURN_ERR;
855 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
856
857 return RETURN_OK;
858}
859
860
861/* wifi_factoryReset() function */
862/**
863* @description Clears internal variables to implement a factory reset of the Wi-Fi
864* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
865*
866* @param None
867*
868* @return The status of the operation.
869* @retval RETURN_OK if successful.
870* @retval RETURN_ERR if any error is detected
871*
872* @execution Synchronous
873* @sideeffect None
874*
875* @note This function must not suspend and must not invoke any blocking system
876* calls. It should probably just send a message to a driver event handler task.
877*
878*/
879INT wifi_factoryReset()
880{
881 char cmd[128];
882
883 /*delete running hostapd conf files*/
developer72ec5572023-01-05 16:27:13 +0800884 wifi_dbg_printf("\n[%s]: deleting hostapd conf file",__func__);
885 sprintf(cmd, "rm -rf /nvram/hostapd*");
developer06a01d92022-09-07 16:32:39 +0800886 system(cmd);
887 system("systemctl restart hostapd.service");
888
889 return RETURN_OK;
890}
891
892/* wifi_factoryResetRadios() function */
893/**
894* @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.
895*
896* @param None
897* @return The status of the operation
898* @retval RETURN_OK if successful
899* @retval RETURN_ERR if any error is detected
900*
901* @execution Synchronous
902*
903* @sideeffect None
904*
905* @note This function must not suspend and must not invoke any blocking system
906* calls. It should probably just send a message to a driver event handler task.
907*
908*/
909INT wifi_factoryResetRadios()
910{
developer72ec5572023-01-05 16:27:13 +0800911 int max_radio_num = 0;
912 wifi_getMaxRadioNumber(&max_radio_num);
913 for (int radioIndex = 0; radioIndex < max_radio_num; radioIndex++)
914 wifi_factoryResetRadio(radioIndex);
developer06a01d92022-09-07 16:32:39 +0800915
developer72ec5572023-01-05 16:27:13 +0800916 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800917}
918
919
920/* wifi_factoryResetRadio() function */
921/**
922* @description Restore selected radio parameters without touching access point parameters
923*
924* @param radioIndex - Index of Wi-Fi Radio channel
925*
926* @return The status of the operation.
927* @retval RETURN_OK if successful.
928* @retval RETURN_ERR if any error is detected
929*
930* @execution Synchronous.
931* @sideeffect None.
932*
933* @note This function must not suspend and must not invoke any blocking system
934* calls. It should probably just send a message to a driver event handler task.
935*
936*/
937INT wifi_factoryResetRadio(int radioIndex) //RDKB
938{
developer72ec5572023-01-05 16:27:13 +0800939 char cmd[128] = {0};
940 char buf[128] = {0};
941 int max_radio_num = 0;
942
943 wifi_getMaxRadioNumber(&max_radio_num);
944 if (radioIndex < 0 || radioIndex > max_radio_num)
945 return RETURN_ERR;
946
947 snprintf(cmd, sizeof(cmd), "systemctl stop hostapd.service");
948 _syscmd(cmd, buf, sizeof(buf));
developer5ff7f5f2022-09-13 15:12:16 +0800949
developer06a01d92022-09-07 16:32:39 +0800950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72ec5572023-01-05 16:27:13 +0800951 snprintf(cmd, sizeof(cmd), "rm /nvram/hostapd%d* %s%d.txt", radioIndex, GUARD_INTERVAL_FILE, radioIndex);
952 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800953
developer72ec5572023-01-05 16:27:13 +0800954 snprintf(cmd, sizeof(cmd), "systemctl start hostapd.service");
955 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800956 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
957 return RETURN_OK;
958}
959
960/* wifi_initRadio() function */
961/**
962* Description: This function call initializes the specified radio.
963* Implementation specifics may dictate the functionality since
964* different hardware implementations may have different initilization requirements.
965* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
966*
967* @return The status of the operation.
968* @retval RETURN_OK if successful.
969* @retval RETURN_ERR if any error is detected
970*
971* @execution Synchronous.
972* @sideeffect None.
973*
974* @note This function must not suspend and must not invoke any blocking system
975* calls. It should probably just send a message to a driver event handler task.
976*
977*/
978INT wifi_initRadio(INT radioIndex)
979{
980 //TODO: Initializes the wifi subsystem (for specified radio)
981 return RETURN_OK;
982}
983void macfilter_init()
984{
985 char count[4]={'\0'};
986 char buf[253]={'\0'};
987 char tmp[19]={'\0'};
988 int dev_count,block,mac_entry=0;
989 char res[4]={'\0'};
990 char acl_file_path[64] = {'\0'};
991 FILE *fp = NULL;
992 int index=0;
993 char iface[10]={'\0'};
994 char config_file[MAX_BUF_SIZE] = {0};
995
996
997 sprintf(acl_file_path,"/tmp/mac_filter.sh");
998
999 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +08001000 if (fp == NULL) {
1001 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
1002 return RETURN_ERR;
1003 }
developer06a01d92022-09-07 16:32:39 +08001004 sprintf(buf,"#!/bin/sh \n");
1005 fprintf(fp,"%s\n",buf);
1006
1007 system("chmod 0777 /tmp/mac_filter.sh");
1008
1009 for(index=0;index<=1;index++)
1010 {
1011 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1012 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1013 sprintf(buf,"syscfg get %dcountfilter",index);
1014 _syscmd(buf,count,sizeof(count));
1015 mac_entry=atoi(count);
1016
1017 sprintf(buf,"syscfg get %dblockall",index);
1018 _syscmd(buf,res,sizeof(res));
1019 block = atoi(res);
1020
1021 //Allow only those macs mentioned in ACL
1022 if(block==1)
1023 {
1024 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1025 fprintf(fp,"%s\n",buf);
1026 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1027 {
1028 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1029 _syscmd(buf,tmp,sizeof(tmp));
1030 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1031 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1032 fprintf(fp,"%s\n",buf);
1033 }
1034 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1035 fprintf(fp,"%s\n",buf);
1036 }
1037
1038 //Block all the macs mentioned in ACL
1039 else if(block==2)
1040 {
1041 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1042 fprintf(fp,"%s\n",buf);
1043
1044 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1045 {
1046 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1047 _syscmd(buf,tmp,sizeof(tmp));
1048 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1049 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1050 fprintf(fp,"%s\n",buf);
1051 }
1052 }
1053 }
1054 fclose(fp);
1055}
1056
1057// Initializes the wifi subsystem (all radios)
1058INT wifi_init() //RDKB
1059{
1060 char interface[MAX_BUF_SIZE]={'\0'};
1061 char bridge_name[MAX_BUF_SIZE]={'\0'};
1062 INT len=0;
1063
1064 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1065 //Not intitializing macfilter for Turris-Omnia Platform for now
1066 //macfilter_init();
1067
1068 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001069 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001070 sleep(2);//sleep to wait for hostapd to start
1071
1072 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1073
1074 return RETURN_OK;
1075}
1076
1077/* wifi_reset() function */
1078/**
1079* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1080* Implementation specifics may dictate what is actualy reset since
1081* different hardware implementations may have different requirements.
1082* Parameters : None
1083*
1084* @return The status of the operation.
1085* @retval RETURN_OK if successful.
1086* @retval RETURN_ERR if any error is detected
1087*
1088* @execution Synchronous.
1089* @sideeffect None.
1090*
1091* @note This function must not suspend and must not invoke any blocking system
1092* calls. It should probably just send a message to a driver event handler task.
1093*
1094*/
1095INT wifi_reset()
1096{
1097 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001098 system("systemctl stop hostapd.service");
1099 sleep(2);
1100 system("systemctl start hostapd.service");
1101 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001102 return RETURN_OK;
1103}
1104
1105/* wifi_down() function */
1106/**
1107* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1108* Implementation specifics may dictate some functionality since
1109* different hardware implementations may have different requirements.
1110*
1111* @param None
1112*
1113* @return The status of the operation
1114* @retval RETURN_OK if successful
1115* @retval RETURN_ERR if any error is detected
1116*
1117* @execution Synchronous
1118* @sideeffect None
1119*
1120* @note This function must not suspend and must not invoke any blocking system
1121* calls. It should probably just send a message to a driver event handler task.
1122*
1123*/
1124INT wifi_down()
1125{
1126 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer72ec5572023-01-05 16:27:13 +08001127 int max_num_radios = 0;
1128 wifi_getMaxRadioNumber(&max_num_radios);
1129 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1130 wifi_setRadioEnable(radioIndex, FALSE);
1131
developer06a01d92022-09-07 16:32:39 +08001132 return RETURN_OK;
1133}
1134
1135
1136/* wifi_createInitialConfigFiles() function */
1137/**
1138* @description This function creates wifi configuration files. The format
1139* and content of these files are implementation dependent. This function call is
1140* used to trigger this task if necessary. Some implementations may not need this
1141* function. If an implementation does not need to create config files the function call can
1142* do nothing and return RETURN_OK.
1143*
1144* @param None
1145*
1146* @return The status of the operation
1147* @retval RETURN_OK if successful
1148* @retval RETURN_ERR if any error is detected
1149*
1150* @execution Synchronous
1151* @sideeffect None
1152*
1153* @note This function must not suspend and must not invoke any blocking system
1154* calls. It should probably just send a message to a driver event handler task.
1155*
1156*/
1157INT wifi_createInitialConfigFiles()
1158{
1159 //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)
1160 return RETURN_OK;
1161}
1162
1163// outputs the country code to a max 64 character string
1164INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1165{
developerd946fd62022-12-08 18:03:28 +08001166 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001167 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001168 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001169 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001170
developerac6f1142022-12-20 19:26:35 +08001171 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001172 return RETURN_ERR;
1173 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001174 _syscmd(cmd, buf, sizeof(buf));
1175 if(strlen(buf) > 0)
1176 snprintf(output_string, 64, "%s", buf);
1177 else
1178 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001179
1180 return RETURN_OK;
1181}
1182
1183INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1184{
1185 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001186 char str[MAX_BUF_SIZE]={'\0'};
1187 char cmd[MAX_CMD_SIZE]={'\0'};
1188 struct params params;
1189 char config_file[MAX_BUF_SIZE] = {0};
1190
1191 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1192 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1193 return RETURN_ERR;
1194
developerb86c6f32022-10-07 14:34:58 +08001195 if (strlen(CountryCode) == 0)
1196 strcpy(CountryCode, "US");
1197
developer7543b3b2022-09-13 13:47:17 +08001198 params.name = "country_code";
1199 params.value = CountryCode;
1200 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1201 int ret = wifi_hostapdWrite(config_file, &params, 1);
1202 if (ret) {
1203 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1204 ,__func__, ret);
1205 }
1206
1207 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1208 if (ret) {
1209 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1210 ,__func__, ret);
1211 }
developer7543b3b2022-09-13 13:47:17 +08001212 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1213
developer06a01d92022-09-07 16:32:39 +08001214 return RETURN_OK;
1215}
1216
developera748dcf2022-09-13 15:56:48 +08001217INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1218{
developerd946fd62022-12-08 18:03:28 +08001219 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001220 char channel_util_file[64] = {0};
1221 char cmd[128] = {0};
1222 char buf[128] = {0};
1223 char line[128] = {0};
1224 char *param = NULL, *value = NULL;
1225 int read = 0;
1226 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1227 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1228 size_t len = 0;
1229 FILE *f = NULL;
1230
1231 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1232
developerac6f1142022-12-20 19:26:35 +08001233 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001234 return RETURN_ERR;
1235 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001236 _syscmd(cmd, buf, sizeof(buf));
1237 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1238
1239 memset(cmd, 0, sizeof(cmd));
1240 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001241 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001242 if ((f = popen(cmd, "r")) == NULL) {
1243 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1244 return RETURN_ERR;
1245 }
1246
1247 read = getline(&line, &len, f);
1248 while (read != -1) {
1249 param = strtok(line, ":\t");
1250 value = strtok(NULL, " ");
1251 if(strstr(param, "frequency") != NULL) {
1252 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1253 }
1254 if(strstr(param, "noise") != NULL) {
1255 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1256 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1257 }
1258 if(strstr(param, "channel active time") != NULL) {
1259 ActiveTime = strtol(value, NULL, 10);
1260 }
1261 if(strstr(param, "channel busy time") != NULL) {
1262 BusyTime = strtol(value, NULL, 10);
1263 }
1264 if(strstr(param, "channel transmit time") != NULL) {
1265 TransmitTime = strtol(value, NULL, 10);
1266 }
1267 read = getline(&line, &len, f);
1268 }
1269 pclose(f);
1270
1271 // The file should store the last active, busy and transmit time
1272 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1273 f = fopen(channel_util_file, "r");
1274 if (f != NULL) {
1275 read = getline(&line, &len, f);
1276 preActiveTime = strtol(line, NULL, 10);
1277 read = getline(&line, &len, f);
1278 preBusyTime = strtol(line, NULL, 10);
1279 read = getline(&line, &len, f);
1280 preTransmitTime = strtol(line, NULL, 10);
1281 fclose(f);
1282 }
1283
1284 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1285 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1286
1287 f = fopen(channel_util_file, "w");
1288 if (f != NULL) {
1289 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1290 fclose(f);
1291 }
1292 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1293 return RETURN_OK;
1294}
1295
developer06a01d92022-09-07 16:32:39 +08001296/**********************************************************************************
1297 *
1298 * Wifi radio level function prototypes
1299 *
1300**********************************************************************************/
1301
1302//Get the total number of radios in this wifi subsystem
1303INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1304{
1305 if (NULL == output)
1306 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001307 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001308
1309 return RETURN_OK;
1310}
1311
1312//Get the total number of SSID entries in this wifi subsystem
1313INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1314{
1315 if (NULL == output)
1316 return RETURN_ERR;
1317 *output = MAX_APS;
1318
1319 return RETURN_OK;
1320}
1321
1322//Get the Radio enable config parameter
1323INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1324{
developerd946fd62022-12-08 18:03:28 +08001325 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001326 char buf[128] = {0}, cmd[128] = {0};
developera77d84b2023-02-22 16:10:50 +08001327 int apIndex;
1328 int max_radio_num = 0;
developer06a01d92022-09-07 16:32:39 +08001329
1330 if (NULL == output_bool)
1331 return RETURN_ERR;
1332
1333 *output_bool = FALSE;
developera77d84b2023-02-22 16:10:50 +08001334
1335 wifi_getMaxRadioNumber(&max_radio_num);
1336
1337 if (radioIndex >= max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001338 return RETURN_ERR;
1339
developera77d84b2023-02-22 16:10:50 +08001340 /* loop all interface in radio, if any is enable, reture true, else return false */
1341 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1342 {
developer643b28f2023-04-04 10:26:01 +08001343 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developera77d84b2023-02-22 16:10:50 +08001344 continue;
1345 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1346 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001347
developera77d84b2023-02-22 16:10:50 +08001348 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 ||
1349 strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0) {
1350 /* return true if any interface is eanble */
1351 *output_bool = TRUE;
1352 break;
1353 }
1354 }
developer06a01d92022-09-07 16:32:39 +08001355 return RETURN_OK;
1356}
1357
1358INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1359{
developerd946fd62022-12-08 18:03:28 +08001360 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001361 char cmd[MAX_CMD_SIZE] = {0};
1362 char buf[MAX_CMD_SIZE] = {0};
1363 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001364 int max_radio_num = 0;
1365 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001366
1367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001368
1369 phyId = radio_index_to_phy(radioIndex);
1370
1371 wifi_getMaxRadioNumber(&max_radio_num);
1372
developer06a01d92022-09-07 16:32:39 +08001373 if(enable==FALSE)
1374 {
developera77d84b2023-02-22 16:10:50 +08001375 /* disable from max apindex to min, to avoid fail in mbss case */
1376 for(apIndex=(MAX_APS-max_radio_num+radioIndex); apIndex>=0; apIndex-=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001377 {
developer1e125222022-12-29 09:35:25 +08001378 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001379 continue;
developer1e125222022-12-29 09:35:25 +08001380
developer06a01d92022-09-07 16:32:39 +08001381 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001382 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001383 _syscmd(cmd, buf, sizeof(buf));
1384 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001385 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001386
developer2f18b9f2023-03-17 19:32:57 +08001387 if (!(apIndex/max_radio_num)) {
1388 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1389 _syscmd(cmd, buf, sizeof(buf));
1390 }
developer06a01d92022-09-07 16:32:39 +08001391 }
developer06a01d92022-09-07 16:32:39 +08001392 }
1393 else
1394 {
developer033b37b2022-10-18 11:27:46 +08001395 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001396 {
developer1e125222022-12-29 09:35:25 +08001397 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001398 continue;
developer1e125222022-12-29 09:35:25 +08001399
developer643b28f2023-04-04 10:26:01 +08001400 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001401 _syscmd(cmd, buf, sizeof(buf));
developera77d84b2023-02-22 16:10:50 +08001402 if(*buf == '1') {
developer2f18b9f2023-03-17 19:32:57 +08001403 if (!(apIndex/max_radio_num)) {
1404 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1405 ret = _syscmd(cmd, buf, sizeof(buf));
1406 if ( ret == RETURN_ERR) {
1407 fprintf(stderr, "VAP interface creation failed\n");
1408 continue;
1409 }
developera77d84b2023-02-22 16:10:50 +08001410 }
developer06a01d92022-09-07 16:32:39 +08001411 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer439baa32024-05-02 15:54:58 +08001412 single_wiphy ? radioIndex : phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001413 _syscmd(cmd, buf, sizeof(buf));
developer439baa32024-05-02 15:54:58 +08001414
developer06a01d92022-09-07 16:32:39 +08001415 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001416 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001417 }
1418 }
1419 }
1420
1421 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1422 return RETURN_OK;
1423}
1424
1425//Get the Radio enable status
1426INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1427{
1428 if (NULL == output_bool)
1429 return RETURN_ERR;
1430
1431 return wifi_getRadioEnable(radioIndex, output_bool);
1432}
1433
1434//Get the Radio Interface name from platform, eg "wlan0"
1435INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1436{
developer804c64f2022-10-19 13:54:40 +08001437 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001438 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001439 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001440}
1441
1442//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1443//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.
1444INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1445{
developerbcc556a2022-09-22 20:02:45 +08001446 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1447 // For max bit rate, we should always choose the best MCS
1448 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001449 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001450 char *tmp = NULL;
1451 UINT mode_map = 0;
1452 UINT num_subcarrier = 0;
1453 UINT code_bits = 0;
1454 float code_rate = 0; // use max code rate
1455 int NSS = 0;
1456 UINT Symbol_duration = 0;
1457 UINT GI_duration = 0;
1458 wifi_band band = band_invalid;
1459 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1460 BOOL enable = FALSE;
1461 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001462
1463 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1464 if (NULL == output_string)
1465 return RETURN_ERR;
1466
developerbcc556a2022-09-22 20:02:45 +08001467 wifi_getRadioEnable(radioIndex, &enable);
1468 if (enable == FALSE) {
1469 snprintf(output_string, 64, "0 Mb/s");
1470 return RETURN_OK;
1471 }
1472
1473 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1474 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1475 return RETURN_ERR;
1476 }
1477
1478 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1479 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1480 return RETURN_ERR;
1481 }
1482
1483 if (gi == wifi_guard_interval_3200)
1484 GI_duration = 32;
1485 else if (gi == wifi_guard_interval_1600)
1486 GI_duration = 16;
1487 else if (gi == wifi_guard_interval_800)
1488 GI_duration = 8;
1489 else // auto, 400
1490 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001491
developerbcc556a2022-09-22 20:02:45 +08001492 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1493 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1494 return RETURN_ERR;
1495 }
1496
1497 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1498 strcpy(channel_bandwidth_str, "160");
1499
1500 if (mode_map & WIFI_MODE_AX) {
1501 if (strstr(channel_bandwidth_str, "160") != NULL)
1502 num_subcarrier = 1960;
1503 else if (strstr(channel_bandwidth_str, "80") != NULL)
1504 num_subcarrier = 980;
1505 else if (strstr(channel_bandwidth_str, "40") != NULL)
1506 num_subcarrier = 468;
1507 else if (strstr(channel_bandwidth_str, "20") != NULL)
1508 num_subcarrier = 234;
1509 code_bits = 10;
1510 code_rate = (float)5/6;
1511 Symbol_duration = 128;
1512 } else if (mode_map & WIFI_MODE_AC) {
1513 if (strstr(channel_bandwidth_str, "160") != NULL)
1514 num_subcarrier = 468;
1515 else if (strstr(channel_bandwidth_str, "80") != NULL)
1516 num_subcarrier = 234;
1517 else if (strstr(channel_bandwidth_str, "40") != NULL)
1518 num_subcarrier = 108;
1519 else if (strstr(channel_bandwidth_str, "20") != NULL)
1520 num_subcarrier = 52;
1521 code_bits = 8;
1522 code_rate = (float)5/6;
1523 Symbol_duration = 32;
1524 } else if (mode_map & WIFI_MODE_N) {
1525 if (strstr(channel_bandwidth_str, "160") != NULL)
1526 num_subcarrier = 468;
1527 else if (strstr(channel_bandwidth_str, "80") != NULL)
1528 num_subcarrier = 234;
1529 else if (strstr(channel_bandwidth_str, "40") != NULL)
1530 num_subcarrier = 108;
1531 else if (strstr(channel_bandwidth_str, "20") != NULL)
1532 num_subcarrier = 52;
1533 code_bits = 6;
1534 code_rate = (float)3/4;
1535 Symbol_duration = 32;
1536 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1537 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1538 snprintf(output_string, 64, "65 Mb/s");
1539 return RETURN_OK;
1540 } else {
1541 snprintf(output_string, 64, "0 Mb/s");
1542 return RETURN_OK;
1543 }
developer06a01d92022-09-07 16:32:39 +08001544
developerbcc556a2022-09-22 20:02:45 +08001545 // Spatial streams
1546 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1547 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1548 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001549 }
developerbcc556a2022-09-22 20:02:45 +08001550
1551 // multiple 10 is to align duration unit (0.1 us)
1552 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1553 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1554
developer06a01d92022-09-07 16:32:39 +08001555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1556
1557 return RETURN_OK;
1558}
1559#if 0
1560INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1561{
1562 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1563 char cmd[64];
1564 char buf[1024];
1565 int apIndex;
1566
1567 if (NULL == output_string)
1568 return RETURN_ERR;
1569
1570 apIndex=(radioIndex==0)?0:1;
1571
developerd946fd62022-12-08 18:03:28 +08001572 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001573 _syscmd(cmd,buf, sizeof(buf));
1574
1575 snprintf(output_string, 64, "%s", buf);
1576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1577 return RETURN_OK;
1578}
1579#endif
1580
1581
1582//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1583//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.
1584INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1585{
developer963da0c2022-09-13 15:58:27 +08001586 wifi_band band = band_invalid;
1587
developer06a01d92022-09-07 16:32:39 +08001588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1589 if (NULL == output_string)
1590 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001591
1592 band = wifi_index_to_band(radioIndex);
1593
1594 memset(output_string, 0, 10);
1595 if (band == band_2_4)
1596 strcpy(output_string, "2.4GHz");
1597 else if (band == band_5)
1598 strcpy(output_string, "5GHz");
1599 else if (band == band_6)
1600 strcpy(output_string, "6GHz");
1601 else
1602 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001603 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1604
1605 return RETURN_OK;
1606#if 0
1607 char buf[MAX_BUF_SIZE]={'\0'};
1608 char str[MAX_BUF_SIZE]={'\0'};
1609 char cmd[MAX_CMD_SIZE]={'\0'};
1610 char *ch=NULL;
1611 char *ch2=NULL;
1612
1613 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1614 if (NULL == output_string)
1615 return RETURN_ERR;
1616
1617
1618 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1619
1620 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1621 {
1622 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1623 return RETURN_ERR;
1624 }
1625 ch=strchr(buf,'\n');
1626 *ch='\0';
1627 ch=strchr(buf,'=');
1628 if(ch==NULL)
1629 return RETURN_ERR;
1630
1631
1632 ch++;
1633
1634 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1635 strcpy(buf,"0");
1636 if(strlen(ch) == 1)
1637 ch=strcat(buf,ch);
1638
1639
1640 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1641
1642 if(_syscmd(cmd,str,64) == RETURN_ERR)
1643 {
1644 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1645 return RETURN_ERR;
1646 }
1647
1648
1649 ch2=strchr(str,'\n');
1650 //replace \n with \0
1651 *ch2='\0';
1652 ch2=strchr(str,'=');
1653 if(ch2==NULL)
1654 {
1655 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1656 return RETURN_ERR;
1657 }
1658 else
1659 wifi_dbg_printf("%s",ch2+1);
1660
1661
1662 ch2++;
1663
1664
1665 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1666
1667 memset(buf,'\0',sizeof(buf));
1668 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1669 {
1670 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1671 return RETURN_ERR;
1672 }
1673 if (strstr(buf,"2.4") != NULL )
1674 strcpy(output_string,"2.4GHz");
1675 else if(strstr(buf,"5.") != NULL )
1676 strcpy(output_string,"5GHz");
1677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1678
1679 return RETURN_OK;
1680#endif
1681}
1682
1683//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1684//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.
1685INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1686{
developerb7593de2022-10-18 09:51:57 +08001687 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001688 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1689 if (NULL == output_string)
1690 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001691 band = wifi_index_to_band(radioIndex);
1692
1693 if (band == band_2_4)
1694 snprintf(output_string, 64, "2.4GHz");
1695 else if (band == band_5)
1696 snprintf(output_string, 64, "5GHz");
1697 else if (band == band_6)
1698 snprintf(output_string, 64, "6GHz");
1699
developer06a01d92022-09-07 16:32:39 +08001700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1701
1702 return RETURN_OK;
1703#if 0
1704 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1705 char buf[MAX_BUF_SIZE]={'\0'};
1706 char str[MAX_BUF_SIZE]={'\0'};
1707 char cmd[MAX_CMD_SIZE]={'\0'};
1708 char *ch=NULL;
1709 char *ch2=NULL;
1710 char ch1[5]="0";
1711
1712 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1713
1714 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1715 {
1716 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1717 return RETURN_ERR;
1718 }
1719
1720 ch=strchr(buf,'\n');
1721 *ch='\0';
1722 ch=strchr(buf,'=');
1723 if(ch==NULL)
1724 return RETURN_ERR;
1725 ch++;
1726
1727 if(strlen(ch)==1)
1728 {
1729 strcat(ch1,ch);
1730
1731 }
1732 else
1733 {
1734 strcpy(ch1,ch);
1735 }
1736
1737
1738
1739 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1740 if(_syscmd(cmd,str,64) == RETURN_ERR)
1741 {
1742 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1743 return RETURN_ERR;
1744 }
1745
1746
1747 ch2=strchr(str,'\n');
1748 //replace \n with \0
1749 *ch2='\0';
1750 ch2=strchr(str,'=');
1751 if(ch2==NULL)
1752 {
1753 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1754 return RETURN_ERR;
1755 }
1756 else
1757 wifi_dbg_printf("%s",ch2+1);
1758 ch2++;
1759
1760
1761 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1762 memset(buf,'\0',sizeof(buf));
1763 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1764 {
1765 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1766 return RETURN_ERR;
1767 }
1768
1769
1770 if(strstr(buf,"2.4")!=NULL)
1771 {
1772 strcpy(output_string,"2.4GHz");
1773 }
1774 if(strstr(buf,"5.")!=NULL)
1775 {
1776 strcpy(output_string,"5GHz");
1777 }
1778 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1779 return RETURN_OK;
1780#endif
1781}
1782
1783//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1784//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.
1785INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1786{
developer963da0c2022-09-13 15:58:27 +08001787 char cmd[128]={0};
1788 char buf[128]={0};
1789 char temp_output[128] = {0};
1790 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001791 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001792
1793 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001794 if (NULL == output_string)
1795 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001796
1797 band = wifi_index_to_band(radioIndex);
1798 if (band == band_2_4) {
1799 strcat(temp_output, "b,g,");
1800 } else if (band == band_5) {
1801 strcat(temp_output, "a,");
1802 }
developer033b37b2022-10-18 11:27:46 +08001803 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001804 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001805 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001806 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001807 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001808 strcat(temp_output, "n,");
1809 }
developer06a01d92022-09-07 16:32:39 +08001810
developer963da0c2022-09-13 15:58:27 +08001811 // vht capabilities
1812 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001813 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001814 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001815 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001816 strcat(temp_output, "ac,");
1817 }
1818 }
1819
1820 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001821 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'", phyId);
developer963da0c2022-09-13 15:58:27 +08001822 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001823 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001824 strcat(temp_output, "ax,");
1825 }
1826
developer7c4cd202023-03-01 10:56:29 +08001827 // eht capabilities
1828 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'EHT MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
1829 _syscmd(cmd, buf, sizeof(buf));
1830 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1831 strcat(temp_output, "be,");
1832 }
1833
developer963da0c2022-09-13 15:58:27 +08001834 // Remove the last comma
1835 if (strlen(temp_output) != 0)
1836 temp_output[strlen(temp_output)-1] = '\0';
1837 strncpy(output_string, temp_output, strlen(temp_output));
1838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001839 return RETURN_OK;
1840}
1841
1842//Get the radio operating mode, and pure mode flag. eg: "ac"
1843//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.
1844INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1845{
1846 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1847 if (NULL == output_string)
1848 return RETURN_ERR;
1849
1850 if (radioIndex == 0) {
1851 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1852 *gOnly = FALSE;
1853 *nOnly = TRUE;
1854 *acOnly = FALSE;
1855 } else {
1856 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1857 *gOnly = FALSE;
1858 *nOnly = FALSE;
1859 *acOnly = FALSE;
1860 }
1861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1862
1863 return RETURN_OK;
1864#if 0
1865 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1866 char buf[64] = {0};
1867 char config_file[MAX_BUF_SIZE] = {0};
1868
1869 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1870 return RETURN_ERR;
1871
1872 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1873 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1874
1875 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1876 if (strlen(buf) == 0)
1877 {
1878 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1879 return RETURN_ERR;
1880 }
1881 if(strcmp(buf,"g")==0)
1882 {
1883 wifi_dbg_printf("\nG\n");
1884 *gOnly=TRUE;
1885 *nOnly=FALSE;
1886 *acOnly=FALSE;
1887 }
1888 else if(strcmp(buf,"n")==0)
1889 {
1890 wifi_dbg_printf("\nN\n");
1891 *gOnly=FALSE;
1892 *nOnly=TRUE;
1893 *acOnly=FALSE;
1894 }
1895 else if(strcmp(buf,"ac")==0)
1896 {
1897 wifi_dbg_printf("\nac\n");
1898 *gOnly=FALSE;
1899 *nOnly=FALSE;
1900 *acOnly=TRUE;
1901 }
1902 /* hostapd-5G.conf has "a" as hw_mode */
1903 else if(strcmp(buf,"a")==0)
1904 {
1905 wifi_dbg_printf("\na\n");
1906 *gOnly=FALSE;
1907 *nOnly=FALSE;
1908 *acOnly=FALSE;
1909 }
1910 else
1911 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1912
1913 //for a,n mode
1914 if(radioIndex == 1)
1915 {
1916 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1917 if(strcmp(buf,"1")==0)
1918 {
1919 strncpy(output_string, "n", 1);
1920 *nOnly=FALSE;
1921 }
1922 }
1923
1924 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1925 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1926 return RETURN_OK;
1927#endif
1928}
1929
developerdb744382022-09-13 15:34:54 +08001930INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1931{
1932 char cmd[128] = {0};
1933 char buf[64] = {0};
1934 char config_file[64] = {0};
1935 wifi_band band;
1936
1937 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1938 if(NULL == output_string || NULL == pureMode)
1939 return RETURN_ERR;
1940
1941 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001942 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer7c4cd202023-03-01 10:56:29 +08001943 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | sed \"s/ieee80211\\.*/\1/\"", config_file);
developerdb744382022-09-13 15:34:54 +08001944 _syscmd(cmd, buf, sizeof(buf));
1945
1946 band = wifi_index_to_band(radioIndex);
1947 // puremode is a bit map
1948 *pureMode = 0;
1949 if (band == band_2_4) {
1950 strcat(output_string, "b,g");
1951 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1952 if (strstr(buf, "n") != NULL) {
1953 strcat(output_string, ",n");
1954 *pureMode |= WIFI_MODE_N;
1955 }
1956 if (strstr(buf, "ax") != NULL) {
1957 strcat(output_string, ",ax");
1958 *pureMode |= WIFI_MODE_AX;
1959 }
developer7c4cd202023-03-01 10:56:29 +08001960 if (strstr(buf, "be") != NULL) {
1961 strcat(output_string, ",be");
1962 *pureMode |= WIFI_MODE_BE;
1963 }
developerdb744382022-09-13 15:34:54 +08001964 } else if (band == band_5) {
1965 strcat(output_string, "a");
1966 *pureMode |= WIFI_MODE_A;
1967 if (strstr(buf, "n") != NULL) {
1968 strcat(output_string, ",n");
1969 *pureMode |= WIFI_MODE_N;
1970 }
1971 if (strstr(buf, "ac") != NULL) {
1972 strcat(output_string, ",ac");
1973 *pureMode |= WIFI_MODE_AC;
1974 }
1975 if (strstr(buf, "ax") != NULL) {
1976 strcat(output_string, ",ax");
1977 *pureMode |= WIFI_MODE_AX;
1978 }
developer7c4cd202023-03-01 10:56:29 +08001979 if (strstr(buf, "be") != NULL) {
1980 strcat(output_string, ",be");
1981 *pureMode |= WIFI_MODE_BE;
1982 }
developerdb744382022-09-13 15:34:54 +08001983 } else if (band == band_6) {
1984 if (strstr(buf, "ax") != NULL) {
1985 strcat(output_string, "ax");
1986 *pureMode |= WIFI_MODE_AX;
1987 }
developer7c4cd202023-03-01 10:56:29 +08001988 if (strstr(buf, "be") != NULL) {
1989 strcat(output_string, ",be");
1990 *pureMode |= WIFI_MODE_BE;
1991 }
developerdb744382022-09-13 15:34:54 +08001992 }
1993
1994 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1995 return RETURN_OK;
1996}
1997
1998// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001999INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2000{
2001 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
2002 if (strcmp (channelMode,"11A") == 0)
2003 {
2004 writeBandWidth(radioIndex,"20MHz");
2005 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2006 printf("\nChannel Mode is 802.11a (5GHz)\n");
2007 }
2008 else if (strcmp (channelMode,"11NAHT20") == 0)
2009 {
2010 writeBandWidth(radioIndex,"20MHz");
2011 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2012 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2013 }
2014 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2015 {
2016 writeBandWidth(radioIndex,"40MHz");
2017 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2018 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2019 }
2020 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2021 {
2022 writeBandWidth(radioIndex,"40MHz");
2023 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2024 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2025 }
2026 else if (strcmp (channelMode,"11ACVHT20") == 0)
2027 {
2028 writeBandWidth(radioIndex,"20MHz");
2029 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2030 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2031 }
2032 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2033 {
2034 writeBandWidth(radioIndex,"40MHz");
2035 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2036 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2037 }
2038 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2039 {
2040 writeBandWidth(radioIndex,"40MHz");
2041 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2042 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2043 }
2044 else if (strcmp (channelMode,"11ACVHT80") == 0)
2045 {
2046 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2047 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2048 }
2049 else if (strcmp (channelMode,"11ACVHT160") == 0)
2050 {
2051 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2052 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2053 }
2054 else if (strcmp (channelMode,"11B") == 0)
2055 {
2056 writeBandWidth(radioIndex,"20MHz");
2057 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2058 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2059 }
2060 else if (strcmp (channelMode,"11G") == 0)
2061 {
2062 writeBandWidth(radioIndex,"20MHz");
2063 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2064 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2065 }
2066 else if (strcmp (channelMode,"11NGHT20") == 0)
2067 {
2068 writeBandWidth(radioIndex,"20MHz");
2069 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2070 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2071 }
2072 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2073 {
2074 writeBandWidth(radioIndex,"40MHz");
2075 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2076 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2077 }
2078 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2079 {
2080 writeBandWidth(radioIndex,"40MHz");
2081 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2082 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2083 }
2084 else
2085 {
2086 return RETURN_ERR;
2087 }
2088 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2089
2090 return RETURN_OK;
2091}
2092
developerdb744382022-09-13 15:34:54 +08002093// Set the radio operating mode, and pure mode flag.
2094INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2095{
developer7c4cd202023-03-01 10:56:29 +08002096 int num_hostapd_support_mode = 4; // n, ac, ax, be
developerdb744382022-09-13 15:34:54 +08002097 struct params list[num_hostapd_support_mode];
2098 char config_file[64] = {0};
2099 char bandwidth[16] = {0};
developer7c4cd202023-03-01 10:56:29 +08002100 char supported_mode[32] = {0};
developerdb744382022-09-13 15:34:54 +08002101 int mode_check_bit = 1 << 3; // n mode
developer7c4cd202023-03-01 10:56:29 +08002102 bool eht_support = FALSE;
developerdb744382022-09-13 15:34:54 +08002103
2104 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2105 // Set radio mode
2106 list[0].name = "ieee80211n";
2107 list[1].name = "ieee80211ac";
2108 list[2].name = "ieee80211ax";
developer7c4cd202023-03-01 10:56:29 +08002109 list[3].name = "ieee80211be";
developerdb744382022-09-13 15:34:54 +08002110 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2111
2112 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002113 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002114 list[0].value = "1";
2115 else
2116 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002117 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002118 list[1].value = "1";
2119 else
2120 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002121 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002122 list[2].value = "1";
2123 else
2124 list[2].value = "0";
developer7c4cd202023-03-01 10:56:29 +08002125 if (pureMode & WIFI_MODE_BE)
2126 list[3].value = "1";
2127 else
2128 list[3].value = "0";
2129
2130 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2131 if (strstr(supported_mode, "be") != NULL)
2132 eht_support = TRUE;
2133
2134 if (eht_support)
2135 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2136 else
2137 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode-1);
developerdb744382022-09-13 15:34:54 +08002138
2139 if (channelMode == NULL || strlen(channelMode) == 0)
2140 return RETURN_OK;
2141 // Set bandwidth
2142 if (strstr(channelMode, "40") != NULL)
2143 strcpy(bandwidth, "40MHz");
2144 else if (strstr(channelMode, "80") != NULL)
2145 strcpy(bandwidth, "80MHz");
2146 else if (strstr(channelMode, "160") != NULL)
2147 strcpy(bandwidth, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002148 else if (strstr(channelMode, "320") != NULL)
2149 strcpy(bandwidth, "320MHz");
developerdb744382022-09-13 15:34:54 +08002150 else // 11A, 11B, 11G....
2151 strcpy(bandwidth, "20MHz");
2152
2153 writeBandWidth(radioIndex, bandwidth);
2154 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2155
2156 wifi_reloadAp(radioIndex);
2157 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2158
2159 return RETURN_OK;
2160}
2161
developer1d12ebf2022-10-04 15:13:38 +08002162INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2163
2164 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002165 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002166 struct params params = {0};
2167 wifi_band band = band_invalid;
2168
2169 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2170
2171 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002172
2173 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002174 return RETURN_ERR;
2175 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2176 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002177 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2178 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002179
2180 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2181 params.name = "hw_mode";
2182 params.value = hw_mode;
2183 wifi_hostapdWrite(config_file, &params, 1);
2184 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2185
developeref938762022-10-19 17:21:01 +08002186 if (band == band_2_4) {
2187 if (strncmp(hw_mode, "b", 1) == 0) {
2188 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2189 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2190 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2191 snprintf(buf, sizeof(buf), "%s", "1,2");
2192 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2193 } else {
2194 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2195
2196 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2197 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2198 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2199 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2200 }
2201 }
2202
developer1d12ebf2022-10-04 15:13:38 +08002203 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2204 return RETURN_OK;
2205}
2206
developere8988ba2022-10-18 17:42:30 +08002207INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2208{
2209 char config_file[64] = {0};
2210 struct params params = {0};
2211 wifi_band band = band_invalid;
2212
2213 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2214
2215 band = wifi_index_to_band(radioIndex);
2216
2217 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2218 params.name = "noscan";
2219 params.value = noscan;
2220 wifi_hostapdWrite(config_file, &params, 1);
2221 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2222
2223 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2224 return RETURN_OK;
2225}
2226
developer06a01d92022-09-07 16:32:39 +08002227//Get the list of supported channel. eg: "1-11"
2228//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.
2229INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2230{
developer6318ed52022-09-13 15:17:58 +08002231 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002232 if (NULL == output_string)
2233 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002234 char cmd[256] = {0};
2235 char buf[128] = {0};
2236 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002237 int phyId = 0;
2238
developer6318ed52022-09-13 15:17:58 +08002239 // Parse possible channel number and separate them with commas.
2240 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002241 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002242 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002243 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002244 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002245 else
developer033b37b2022-10-18 11:27:46 +08002246 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002247
2248 _syscmd(cmd,buf,sizeof(buf));
2249 strncpy(output_string, buf, sizeof(buf));
2250
2251 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2252 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002253}
2254
2255//Get the list for used channel. eg: "1,6,9,11"
2256//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.
2257INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2258{
developerd946fd62022-12-08 18:03:28 +08002259 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002260 char cmd[128] = {0};
2261 char buf[128] = {0};
2262 char config_file[64] = {0};
2263 int channel = 0;
2264 int freq = 0;
2265 int bandwidth = 0;
2266 int center_freq = 0;
2267 int center_channel = 0;
2268 int channel_delta = 0;
2269 wifi_band band = band_invalid;
2270
2271 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2272
developer06a01d92022-09-07 16:32:39 +08002273 if (NULL == output_string)
2274 return RETURN_ERR;
2275
developerac6f1142022-12-20 19:26:35 +08002276 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002277 return RETURN_ERR;
2278 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002279 _syscmd(cmd, buf, sizeof(buf));
2280 if (strlen(buf) == 0) {
2281 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2282 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002283 }
developerf5745ee2022-10-05 16:09:53 +08002284 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2285
2286 if (bandwidth == 20) {
2287 snprintf(output_string, 256, "%d", channel);
2288 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002289 }
developerf5745ee2022-10-05 16:09:53 +08002290
2291 center_channel = ieee80211_frequency_to_channel(center_freq);
2292
2293 band = wifi_index_to_band(radioIndex);
2294 if (band == band_2_4 && bandwidth == 40) {
2295 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2296 memset(buf, 0, sizeof(buf));
2297 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2298
developerf22724d2022-12-22 17:24:14 +08002299 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002300 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002301 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002302 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2303 } else {
2304 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2305 return RETURN_ERR;
2306 }
2307 } else if (band == band_5 || band == band_6){
2308 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
developer72ec5572023-01-05 16:27:13 +08002309 // example: bandwidth 80: center is 42 (5210), channels are "36,40,44,48" (5170-5250). The delta should be 6.
developerf5745ee2022-10-05 16:09:53 +08002310 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002311 memset(output_string, 0, 256);
2312 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2313 // If i is not the last channel, we add a comma.
2314 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2315 strncat(output_string, buf, strlen(buf));
2316 }
developerf5745ee2022-10-05 16:09:53 +08002317 } else
2318 return RETURN_ERR;
2319
2320 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002321 return RETURN_OK;
2322}
2323
2324//Get the running channel number
2325INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2326{
developer5b398df2022-11-17 20:39:48 +08002327 char channel_str[16] = {0};
2328 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002329
developer5b398df2022-11-17 20:39:48 +08002330 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002331 return RETURN_ERR;
2332
developer5b398df2022-11-17 20:39:48 +08002333 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2334 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002335
developer5b398df2022-11-17 20:39:48 +08002336 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002337
developer06a01d92022-09-07 16:32:39 +08002338 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002339}
2340
2341
2342INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2343{
2344 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002345 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002346
2347 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2348 if (NULL == output_ulong)
2349 return RETURN_ERR;
2350
developer06a01d92022-09-07 16:32:39 +08002351 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002352 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2353 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002354 _syscmd(cmd,buf,sizeof(buf));
2355 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2356 if (*output_ulong == 0) {
2357 return RETURN_ERR;
2358 }
2359
2360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2361 return RETURN_OK;
2362}
2363
2364//Storing the previous channel value
2365INT wifi_storeprevchanval(INT radioIndex)
2366{
2367 char buf[256] = {0};
2368 char output[4]={'\0'};
2369 char config_file[MAX_BUF_SIZE] = {0};
2370 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2371 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2372 if(radioIndex == 0)
2373 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2374 else if(radioIndex == 1)
2375 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2376 system(buf);
2377 Radio_flag = FALSE;
2378 return RETURN_OK;
2379}
2380
2381//Set the running channel number
2382INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2383{
developer76989232022-10-04 14:13:19 +08002384 // We only write hostapd config here
2385 char str_channel[8]={0};
2386 char *list_channel;
2387 char config_file[128] = {0};
2388 char possible_channels[256] = {0};
2389 int max_radio_num = 0;
2390 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002391
developer76989232022-10-04 14:13:19 +08002392 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002393
developer76989232022-10-04 14:13:19 +08002394 // Check valid
2395 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002396
developer76989232022-10-04 14:13:19 +08002397 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2398 list_channel = strtok(possible_channels, ",");
2399 while(true)
developer06a01d92022-09-07 16:32:39 +08002400 {
developer76989232022-10-04 14:13:19 +08002401 if(list_channel == NULL) { // input not in the list
2402 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2403 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002404 }
developer76989232022-10-04 14:13:19 +08002405 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2406 break;
2407 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002408 }
2409
developer76989232022-10-04 14:13:19 +08002410 list.name = "channel";
2411 list.value = str_channel;
2412 wifi_getMaxRadioNumber(&max_radio_num);
2413 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002414 {
developer76989232022-10-04 14:13:19 +08002415 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2416 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002417 }
2418
developer76989232022-10-04 14:13:19 +08002419 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002420 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002421}
developer06a01d92022-09-07 16:32:39 +08002422
2423INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2424{
developer7c4cd202023-03-01 10:56:29 +08002425 struct params list[3];
2426 char str_idx[16] = {0};
2427 char supported_mode[32] = {0};
2428 char config_file[64] = {0};
developer76989232022-10-04 14:13:19 +08002429 int max_num_radios = 0;
2430 wifi_band band = band_invalid;
developer7c4cd202023-03-01 10:56:29 +08002431 bool eht_support = FALSE;
developer76989232022-10-04 14:13:19 +08002432
2433 band = wifi_index_to_band(radioIndex);
2434 if (band == band_2_4)
2435 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002436
developer7c4cd202023-03-01 10:56:29 +08002437 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2438 if (strstr(supported_mode, "be") != NULL)
2439 eht_support = TRUE;
2440
developer30423732022-12-01 16:17:49 +08002441 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002442 list[0].name = "vht_oper_centr_freq_seg0_idx";
2443 list[0].value = str_idx;
2444 list[1].name = "he_oper_centr_freq_seg0_idx";
2445 list[1].value = str_idx;
developer7c4cd202023-03-01 10:56:29 +08002446 list[2].name = "eht_oper_centr_freq_seg0_idx";
2447 list[2].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002448
developer76989232022-10-04 14:13:19 +08002449 wifi_getMaxRadioNumber(&max_num_radios);
2450 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002451 {
developer76989232022-10-04 14:13:19 +08002452 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
developer7c4cd202023-03-01 10:56:29 +08002453 if (eht_support)
2454 wifi_hostapdWrite(config_file, list, 3);
developer76989232022-10-04 14:13:19 +08002455 else
2456 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002457 }
2458
2459 return RETURN_OK;
2460}
2461
2462//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2463//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2464INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2465{
2466 //Set to wifi config only. Wait for wifi reset to apply.
2467 char buf[256] = {0};
2468 char str_channel[256] = {0};
2469 int count = 0;
2470 ULONG Value = 0;
2471 FILE *fp = NULL;
2472 if(enable == TRUE)
2473 {
developer06a01d92022-09-07 16:32:39 +08002474 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002475 }
developer5884e982022-10-06 10:52:50 +08002476 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002477}
2478
developer0b246d12022-09-30 15:24:20 +08002479INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2480{
2481 if (output_bool == NULL)
2482 return RETURN_ERR;
2483
2484 *output_bool = TRUE;
2485
2486 return RETURN_OK;
2487}
2488
developer06a01d92022-09-07 16:32:39 +08002489INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2490{
2491 if (NULL == output_bool)
2492 return RETURN_ERR;
2493 *output_bool=FALSE;
2494 return RETURN_OK;
2495}
2496
2497INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2498{
2499 if (NULL == output_bool)
2500 return RETURN_ERR;
2501 *output_bool=FALSE;
2502 return RETURN_OK;
2503}
2504
2505INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2506{
2507 //Set to wifi config only. Wait for wifi reset to apply.
2508 return RETURN_OK;
2509}
2510
2511INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2512{
2513 return RETURN_OK;
2514}
2515
2516INT wifi_factoryResetAP(int apIndex)
2517{
developer838cca92022-10-03 13:19:57 +08002518 char ap_config_file[64] = {0};
2519 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002520 char buf[128] = {0};
developer89df4502023-02-16 20:45:02 +08002521 int max_radio_num = 0;
developer838cca92022-10-03 13:19:57 +08002522
developer06a01d92022-09-07 16:32:39 +08002523 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002524
2525 wifi_setApEnable(apIndex, FALSE);
2526 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2527 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002528 _syscmd(cmd, buf, sizeof(buf));
developer89df4502023-02-16 20:45:02 +08002529 wifi_getMaxRadioNumber(&max_radio_num);
2530 if (apIndex <= max_radio_num) // The ap is default radio interface, we should default up it.
2531 wifi_setApEnable(apIndex, TRUE);
developer838cca92022-10-03 13:19:57 +08002532
developer06a01d92022-09-07 16:32:39 +08002533 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002534
developer06a01d92022-09-07 16:32:39 +08002535 return RETURN_OK;
2536}
2537
2538//To set Band Steering AP group
2539//To-do
2540INT wifi_setBandSteeringApGroup(char *ApGroup)
2541{
2542 return RETURN_OK;
2543}
2544
developer1e5aa162022-09-13 16:06:24 +08002545INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2546{
2547 char config_file[128] = {'\0'};
2548 char buf[128] = {'\0'};
2549
2550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2551 if (dtimInterval == NULL)
2552 return RETURN_ERR;
2553
2554 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2555 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2556
2557 if (strlen(buf) == 0) {
2558 *dtimInterval = 2;
2559 } else {
2560 *dtimInterval = strtoul(buf, NULL, 10);
2561 }
2562
2563 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2564 return RETURN_OK;
2565}
2566
developer06a01d92022-09-07 16:32:39 +08002567INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2568{
developer5f222492022-09-13 15:21:52 +08002569 struct params params={0};
2570 char config_file[MAX_BUF_SIZE] = {'\0'};
2571 char buf[MAX_BUF_SIZE] = {'\0'};
2572
2573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2574 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002575 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002576 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002577 }
2578
2579 params.name = "dtim_period";
2580 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2581 params.value = buf;
2582
2583 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2584 wifi_hostapdWrite(config_file, &params, 1);
2585 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2586
2587 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2588 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002589}
2590
2591//Check if the driver support the Dfs
2592INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2593{
developer78a15382022-11-02 10:57:40 +08002594 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002595 if (NULL == output_bool)
2596 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002597 *output_bool=FALSE;
2598
2599 band = wifi_index_to_band(radioIndex);
2600 if (band == band_5)
2601 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002602 return RETURN_OK;
2603}
2604
2605//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.
2606//The value of this parameter is a comma seperated list of channel number
2607INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2608{
2609 if (NULL == output_pool)
2610 return RETURN_ERR;
2611 if (radioIndex==1)
2612 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2613 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2614
2615 return RETURN_OK;
2616}
2617
2618INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2619{
2620 //Set to wifi config. And apply instantly.
2621 return RETURN_OK;
2622}
2623
2624INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2625{
2626 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2627 return RETURN_ERR;
2628 *output_interval_seconds=1800;
2629 *output_dwell_milliseconds=40;
2630
2631 return RETURN_OK;
2632}
2633
2634INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2635{
2636 //Set to wifi config. And apply instantly.
2637 return RETURN_OK;
2638}
2639
developerbfc18512022-10-05 17:54:28 +08002640INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2641{
2642 if (output_bool == NULL)
2643 return RETURN_ERR;
2644 *output_bool = true;
2645 return RETURN_OK;
2646}
2647
2648INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2649{
2650 return RETURN_OK;
2651}
2652
developer06a01d92022-09-07 16:32:39 +08002653//Get the Dfs enable status
2654INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2655{
developer9964b5b2022-09-13 15:59:34 +08002656 char buf[16] = {0};
2657 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002658
2659 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2660
developer30423732022-12-01 16:17:49 +08002661 if (output_bool == NULL)
2662 return RETURN_ERR;
2663
developer9964b5b2022-09-13 15:59:34 +08002664 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002665 f = fopen(DFS_ENABLE_FILE, "r");
2666 if (f != NULL) {
2667 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002668 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002669 *output_bool = FALSE;
2670 fclose(f);
2671 }
2672 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002673 return RETURN_OK;
2674}
2675
2676//Set the Dfs enable status
2677INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2678{
developer9964b5b2022-09-13 15:59:34 +08002679 char config_file[128] = {0};
2680 FILE *f = NULL;
2681 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002682
2683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2684
developer9964b5b2022-09-13 15:59:34 +08002685 f = fopen(DFS_ENABLE_FILE, "w");
2686 if (f == NULL)
2687 return RETURN_ERR;
2688 fprintf(f, "%d", enable);
2689 fclose(f);
2690
2691 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002692 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002693 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2694 wifi_hostapdWrite(config_file, &params, 1);
2695 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2696
2697 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2698
developer9964b5b2022-09-13 15:59:34 +08002699 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002700 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002701}
2702
2703//Check if the driver support the AutoChannelRefreshPeriod
2704INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2705{
2706 if (NULL == output_bool)
2707 return RETURN_ERR;
2708 *output_bool=FALSE; //not support
2709
2710 return RETURN_OK;
2711}
2712
2713//Get the ACS refresh period in seconds
2714INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2715{
2716 if (NULL == output_ulong)
2717 return RETURN_ERR;
2718 *output_ulong=300;
2719
2720 return RETURN_OK;
2721}
2722
2723//Set the ACS refresh period in seconds
2724INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2725{
2726 return RETURN_ERR;
2727}
2728
developer7c4cd202023-03-01 10:56:29 +08002729INT getEHT320ChannelBandwidthSet(int radioIndex, int *BandwidthSet)
2730{
2731 int center_channel = 0;
2732 char config_file[32] = {0};
2733 char buf[32] = {0};
2734
2735 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2736 wifi_hostapdRead(config_file, "eht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2737
2738 center_channel = strtoul(buf, NULL, 10);
2739 center_channel += 1; // Add 1 to become muiltiple of 16
2740 if (center_channel % 64 == 32)
2741 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_1MHZ;
2742 else if (center_channel % 64 == 0)
2743 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_2MHZ;
2744 else
2745 return RETURN_ERR;
2746 return RETURN_OK;
2747}
2748
developer06a01d92022-09-07 16:32:39 +08002749//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2750//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.
2751INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2752{
developer72ec5572023-01-05 16:27:13 +08002753 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002754 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002755 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002756 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002757 wifi_band band;
developer70490032022-09-13 15:45:20 +08002758
2759 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2760
developer06a01d92022-09-07 16:32:39 +08002761 if (NULL == output_string)
2762 return RETURN_ERR;
2763
developer70490032022-09-13 15:45:20 +08002764 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2765 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002766
developer70490032022-09-13 15:45:20 +08002767 if (radio_enable != TRUE)
2768 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002769
developerfa41b1f2023-01-06 10:25:51 +08002770 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002771 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002772 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002773 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2774 snprintf(output_string, 64, "20MHz");
2775 else
2776 snprintf(output_string, 64, "40MHz");
2777
2778 } else {
2779 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2780 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2781 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2782 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2783 if (strncmp(buf, "0", 1) == 0)
2784 snprintf(output_string, 64, "20MHz");
2785 else
2786 snprintf(output_string, 64, "40MHz");
2787
2788 } else if (strncmp(buf, "1", 1) == 0)
2789 snprintf(output_string, 64, "80MHz");
developer7c4cd202023-03-01 10:56:29 +08002790 else if (strncmp(buf, "2", 1) == 0) {
developer72ec5572023-01-05 16:27:13 +08002791 snprintf(output_string, 64, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002792 wifi_hostapdRead(config_file, "eht_oper_chwidth", buf, sizeof(buf));
2793 if (strncmp(buf, "9", 1) == 0) {
2794 int BandwidthSet = 0;
2795 if (getEHT320ChannelBandwidthSet(radioIndex, &BandwidthSet) != RETURN_OK)
2796 return RETURN_ERR;
2797 if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_1MHZ)
2798 snprintf(output_string, 64, "320-1MHz");
2799 else if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_2MHZ)
2800 snprintf(output_string, 64, "320-2MHz");
2801 }
2802 }
developer06a01d92022-09-07 16:32:39 +08002803 }
developer72ec5572023-01-05 16:27:13 +08002804
developer06a01d92022-09-07 16:32:39 +08002805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002806
2807 return RETURN_OK;
2808}
2809
2810//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002811INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002812{
developerf7a466e2022-09-29 11:55:56 +08002813 char config_file[128];
2814 char set_value[16];
developer7c4cd202023-03-01 10:56:29 +08002815 char supported_mode[32] = {0};
2816 struct params params[3];
developerf7a466e2022-09-29 11:55:56 +08002817 int max_radio_num = 0;
developer7c4cd202023-03-01 10:56:29 +08002818 bool eht_support = FALSE;
developerf7a466e2022-09-29 11:55:56 +08002819
developer06a01d92022-09-07 16:32:39 +08002820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002821
developerf7a466e2022-09-29 11:55:56 +08002822 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002823 return RETURN_ERR;
2824
developer7c4cd202023-03-01 10:56:29 +08002825 if(strstr(bandwidth,"160") != NULL || strstr(bandwidth,"320") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002826 strcpy(set_value, "2");
2827 else if(strstr(bandwidth,"80") != NULL)
2828 strcpy(set_value, "1");
2829 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2830 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002831 else if (strstr(bandwidth, "Auto") != NULL)
2832 return RETURN_OK;
2833 else {
developerf7a466e2022-09-29 11:55:56 +08002834 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002835 return RETURN_ERR;
2836 }
2837
developer7c4cd202023-03-01 10:56:29 +08002838 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2839 if (strstr(supported_mode, "be") != NULL)
2840 eht_support = TRUE;
2841
developerf7a466e2022-09-29 11:55:56 +08002842 params[0].name = "vht_oper_chwidth";
2843 params[0].value = set_value;
2844 params[1].name = "he_oper_chwidth";
2845 params[1].value = set_value;
developer7c4cd202023-03-01 10:56:29 +08002846 params[2].name = "eht_oper_chwidth";
2847 if (strstr(bandwidth,"320") != NULL) // We set oper_chwidth to 9 for EHT320
2848 params[2].value = "9";
2849 else
2850 params[2].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002851
developerf7a466e2022-09-29 11:55:56 +08002852 wifi_getMaxRadioNumber(&max_radio_num);
2853 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002854 {
developer7c4cd202023-03-01 10:56:29 +08002855 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2856 if (eht_support == TRUE)
2857 wifi_hostapdWrite(config_file, params, 3);
2858 else
2859 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002860 }
2861
2862 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2863 return RETURN_OK;
2864}
2865
2866//Getting current radio extension channel
2867INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2868{
2869 CHAR buf[150] = {0};
2870 CHAR cmd[150] = {0};
2871 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2872 _syscmd(cmd, buf, sizeof(buf));
2873 if(NULL != strstr(buf,"HT40+"))
2874 strcpy(Value,"AboveControlChannel");
2875 else if(NULL != strstr(buf,"HT40-"))
2876 strcpy(Value,"BelowControlChannel");
2877 return RETURN_OK;
2878}
2879
2880//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2881//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.
2882INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2883{
developerfa41b1f2023-01-06 10:25:51 +08002884 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002885 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002886
2887 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002888 return RETURN_ERR;
2889
developerfa41b1f2023-01-06 10:25:51 +08002890 band = wifi_index_to_band(radioIndex);
2891 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002892 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002893
2894 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2895
2896 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002897 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002898
2899 return RETURN_OK;
2900}
2901
developer57fa24a2023-03-15 17:25:07 +08002902// This function handle 20MHz to remove HT40+/- in hostapd config, other bandwidths are handled in wifi_setRadioExtChannel.
2903INT wifi_RemoveRadioExtChannel(INT radioIndex, CHAR *ext_str)
2904{
2905 struct params params={0};
2906 char config_file[64] = {0};
2907 char ht_capab[128]={0};
2908 char buf[128] = {0};
2909 char cmd[128] = {0};
2910 int max_radio_num =0;
2911 bool stbcEnable = FALSE;
2912
2913 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2914 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2915 _syscmd(cmd, buf, sizeof(buf));
2916 if (strlen(buf) != 0)
2917 stbcEnable = TRUE;
2918
2919 strcpy(ht_capab, HOSTAPD_HT_CAPAB);
2920 params.value = ht_capab;
2921 params.name = "ht_capab";
2922
2923 wifi_getMaxRadioNumber(&max_radio_num);
2924 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2925 {
2926 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2927 wifi_hostapdWrite(config_file, &params, 1);
developer57fa24a2023-03-15 17:25:07 +08002928 }
developer8d7d0862023-05-18 16:50:23 +08002929 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer57fa24a2023-03-15 17:25:07 +08002930 return RETURN_OK;
2931}
2932
developer06a01d92022-09-07 16:32:39 +08002933//Set the extension channel.
2934INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer72ec5572023-01-05 16:27:13 +08002935{
developer06a01d92022-09-07 16:32:39 +08002936 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002937 struct params params={0};
2938 char config_file[64] = {0};
2939 char ext_channel[128]={0};
2940 char buf[128] = {0};
2941 char cmd[128] = {0};
2942 int max_radio_num =0, ret = 0, bandwidth = 0;
developer72ec5572023-01-05 16:27:13 +08002943 unsigned long channel = 0;
developerfa41b1f2023-01-06 10:25:51 +08002944 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002945 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002946 wifi_band band;
2947
2948 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2949 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2950 _syscmd(cmd, buf, sizeof(buf));
2951 if (strlen(buf) != 0)
2952 stbcEnable = TRUE;
developer57fa24a2023-03-15 17:25:07 +08002953
2954 // readBandWidth get empty file will return error, that means we don't set new bandwidth
2955 if (readBandWidth(radioIndex, buf) != RETURN_OK) {
2956 // Get current bandwidth
2957 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2958 return RETURN_ERR;
2959 }
developerfa41b1f2023-01-06 10:25:51 +08002960 bandwidth = strtol(buf, NULL, 10);
2961 // TDK expected to get error with 20MHz
developer57fa24a2023-03-15 17:25:07 +08002962 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developerfa41b1f2023-01-06 10:25:51 +08002963 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2964 return RETURN_ERR;
2965
2966 band = wifi_index_to_band(radioIndex);
2967 if (band == band_invalid)
2968 return RETURN_ERR;
2969
2970 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2971 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002972
developer72ec5572023-01-05 16:27:13 +08002973 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2974 ret = util_get_sec_chan_offset(channel, buf);
2975 if (ret == -EINVAL)
2976 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002977
2978 if(NULL!= strstr(string,"Above")) {
developer72ec5572023-01-05 16:27:13 +08002979 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
2980 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002981 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08002982 } else if(NULL!= strstr(string,"Below")) {
developer72ec5572023-01-05 16:27:13 +08002983 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == 1))
2984 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002985 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08002986 } else {
developer57fa24a2023-03-15 17:25:07 +08002987 fprintf(stderr, "%s: unknow extchannel %s\n", __func__, string);
2988 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002989 }
developer06a01d92022-09-07 16:32:39 +08002990
2991 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002992
2993 wifi_getMaxRadioNumber(&max_radio_num);
2994 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002995 {
developer033b37b2022-10-18 11:27:46 +08002996 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002997 wifi_hostapdWrite(config_file, &params, 1);
2998 }
developer8d7d0862023-05-18 16:50:23 +08002999 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer06a01d92022-09-07 16:32:39 +08003000
3001 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3002 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3003 return RETURN_OK;
3004}
3005
3006//Get the guard interval value. eg "400nsec" or "800nsec"
3007//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.
3008INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3009{
developer454b9462022-09-13 15:29:16 +08003010 wifi_guard_interval_t GI;
3011
3012 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3013
3014 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08003015 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08003016
3017 if (GI == wifi_guard_interval_400)
3018 strcpy(output_string, "400nsec");
3019 else if (GI == wifi_guard_interval_800)
3020 strcpy(output_string, "800nsec");
3021 else if (GI == wifi_guard_interval_1600)
3022 strcpy(output_string, "1600nsec");
3023 else if (GI == wifi_guard_interval_3200)
3024 strcpy(output_string, "3200nsec");
3025 else
developer78a15382022-11-02 10:57:40 +08003026 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08003027
developer454b9462022-09-13 15:29:16 +08003028 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003029 return RETURN_OK;
3030}
3031
3032//Set the guard interval value.
3033INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3034{
developer454b9462022-09-13 15:29:16 +08003035 wifi_guard_interval_t GI;
3036 int ret = 0;
3037
3038 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3039
3040 if (strcmp(string, "400nsec") == 0)
3041 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08003042 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08003043 GI = wifi_guard_interval_800;
3044 else if (strcmp(string , "1600nsec") == 0)
3045 GI = wifi_guard_interval_1600;
3046 else if (strcmp(string , "3200nsec") == 0)
3047 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08003048 else
3049 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08003050
3051 ret = wifi_setGuardInterval(radioIndex, GI);
3052
3053 if (ret == RETURN_ERR) {
3054 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3055 return RETURN_ERR;
3056 }
3057
3058 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3059 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003060}
3061
3062//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3063INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3064{
developerf49437e2022-09-29 19:58:21 +08003065 char buf[32]={0};
3066 char mcs_file[64] = {0};
3067 char cmd[64] = {0};
3068 int mode_bitmap = 0;
3069
3070 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3071 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08003072 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08003073 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3074
3075 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3076 _syscmd(cmd, buf, sizeof(buf));
3077 if (strlen(buf) > 0)
3078 *output_int = strtol(buf, NULL, 10);
3079 else {
3080 // output the max MCS for the current radio mode
3081 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3082 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3083 return RETURN_ERR;
3084 }
3085 if (mode_bitmap & WIFI_MODE_AX) {
3086 *output_int = 11;
3087 } else if (mode_bitmap & WIFI_MODE_AC) {
3088 *output_int = 9;
3089 } else if (mode_bitmap & WIFI_MODE_N) {
3090 *output_int = 7;
3091 }
3092 }
3093 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003094
3095 return RETURN_OK;
3096}
3097
3098//Set the Modulation Coding Scheme index
3099INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3100{
developerf49437e2022-09-29 19:58:21 +08003101 // 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).
3102 char config_file[64] = {0};
3103 char set_value[16] = {0};
3104 char mcs_file[32] = {0};
3105 wifi_band band = band_invalid;
3106 struct params set_config = {0};
3107 FILE *f = NULL;
3108
3109 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3110
3111 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3112
developer78a15382022-11-02 10:57:40 +08003113 // -1 means auto
3114 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08003115 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3116 return RETURN_ERR;
3117 }
3118
developer78a15382022-11-02 10:57:40 +08003119 if (MCS > 9 || MCS == -1)
3120 strcpy(set_value, "2");
3121 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08003122 strcpy(set_value, "1");
3123 else
developer78a15382022-11-02 10:57:40 +08003124 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08003125
3126 set_config.name = "he_basic_mcs_nss_set";
3127 set_config.value = set_value;
3128
3129 wifi_hostapdWrite(config_file, &set_config, 1);
3130 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3131
3132 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3133 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3134 f = fopen(mcs_file, "w");
3135 if (f == NULL) {
3136 fprintf(stderr, "%s: fopen failed\n", __func__);
3137 return RETURN_ERR;
3138 }
3139 fprintf(f, "%d", MCS);
3140 fclose(f);
3141
3142 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3143 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003144}
3145
3146//Get supported Transmit Power list, eg : "0,25,50,75,100"
3147//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.
3148INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3149{
3150 if (NULL == output_list)
3151 return RETURN_ERR;
developer5c97d532023-09-28 11:19:30 +08003152 snprintf(output_list, 64,"0,12,25,50,75,100");
developer06a01d92022-09-07 16:32:39 +08003153 return RETURN_OK;
3154}
3155
developer5c97d532023-09-28 11:19:30 +08003156// Get current Transmit Power in percent
developer06a01d92022-09-07 16:32:39 +08003157INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3158{
developer5c97d532023-09-28 11:19:30 +08003159 char cmd[128]={'\0'};
3160 char buf[128]={'\0'};
3161 int phyIndex = -1;
3162 bool enabled = false;
3163 int cur_tx_dbm = 0;
3164
developera5005b62022-09-13 15:43:35 +08003165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003166
developera5005b62022-09-13 15:43:35 +08003167 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003168 return RETURN_ERR;
3169
developer5c97d532023-09-28 11:19:30 +08003170 phyIndex = radio_index_to_phy(radioIndex);
3171
3172 // Get the maximum tx power of the device
3173 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +08003174 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developer06a01d92022-09-07 16:32:39 +08003175 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003176 if (strcmp(buf, "enable") == 0)
3177 enabled = true;
developer06a01d92022-09-07 16:32:39 +08003178
developer5c97d532023-09-28 11:19:30 +08003179 if (!enabled) {
3180 *output_ulong = 100;
3181 return RETURN_OK;
3182 }
developera5005b62022-09-13 15:43:35 +08003183
developer5c97d532023-09-28 11:19:30 +08003184 memset(cmd, 0, sizeof(cmd));
3185 memset(buf, 0, sizeof(buf));
3186 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +08003187 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developer5c97d532023-09-28 11:19:30 +08003188 _syscmd(cmd, buf, sizeof(buf));
3189 cur_tx_dbm = strtol(buf, NULL, 10);
3190
3191 switch (cur_tx_dbm) {
3192 case 0:
3193 *output_ulong = 100; // range 91-100
3194 break;
3195 case 1:
3196 *output_ulong = 75; // range 61-90
3197 break;
3198 case 3:
3199 *output_ulong = 50; // range 31-60
3200 break;
3201 case 6:
3202 *output_ulong = 25; // range 16-30
3203 break;
3204 case 9:
3205 *output_ulong = 12; // range 10-15
3206 break;
3207 case 12:
3208 *output_ulong = 6; // range 1-9
3209 break;
3210 default:
3211 *output_ulong = 100; // 0
3212 }
3213
developer06a01d92022-09-07 16:32:39 +08003214 return RETURN_OK;
3215}
3216
developer5c97d532023-09-28 11:19:30 +08003217// TransmitPower: the the percentage relative to the maximum power,
3218// only support 0,12,25,50,75,100, But 0 means disable Power limit,
3219// so the power is 100%
developer06a01d92022-09-07 16:32:39 +08003220INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3221{
developerd946fd62022-12-08 18:03:28 +08003222 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003223 char *support;
developer06a01d92022-09-07 16:32:39 +08003224 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003225 char buf[128]={0};
3226 char txpower_str[64] = {0};
developer033b37b2022-10-18 11:27:46 +08003227 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003228
3229 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003230
developerac6f1142022-12-20 19:26:35 +08003231 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003232 return RETURN_ERR;
developera5005b62022-09-13 15:43:35 +08003233
3234 // Get the Tx power supported list and check that is the input in the list
3235 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3236 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3237 support = strtok(buf, ",");
3238 while(true)
3239 {
3240 if(support == NULL) { // input not in the list
3241 wifi_dbg_printf("Input value is invalid.\n");
3242 return RETURN_ERR;
3243 }
3244 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3245 break;
3246 }
3247 support = strtok(NULL, ",");
3248 }
developer5c97d532023-09-28 11:19:30 +08003249
developer033b37b2022-10-18 11:27:46 +08003250 phyId = radio_index_to_phy(radioIndex);
developer5c97d532023-09-28 11:19:30 +08003251 snprintf(cmd, sizeof(cmd), "echo %lu > /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_level",
developer439baa32024-05-02 15:54:58 +08003252 TransmitPower, single_wiphy ? radioIndex : phyId);
developera5005b62022-09-13 15:43:35 +08003253 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003254
developera5005b62022-09-13 15:43:35 +08003255 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003256
3257 return RETURN_OK;
3258}
3259
3260//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3261INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3262{
3263 if (NULL == Supported)
3264 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003265 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003266
3267 return RETURN_OK;
3268}
3269
3270//Get 80211h feature enable
3271INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3272{
developer3885fec2022-09-13 15:13:47 +08003273 char buf[64]={'\0'};
3274 char config_file[64] = {'\0'};
3275
3276 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3277 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003278 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003279
3280 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3281 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003282
developer3885fec2022-09-13 15:13:47 +08003283 if (strncmp(buf, "1", 1) == 0)
3284 *enable = TRUE;
3285 else
3286 *enable = FALSE;
3287
3288 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003289 return RETURN_OK;
3290}
3291
3292//Set 80211h feature enable
3293INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3294{
developer3885fec2022-09-13 15:13:47 +08003295 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3296 struct params params={'\0'};
3297 char config_file[MAX_BUF_SIZE] = {0};
3298
3299 params.name = "ieee80211h";
3300
3301 if (enable) {
3302 params.value = "1";
3303 } else {
3304 params.value = "0";
3305 }
3306
3307 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3308 wifi_hostapdWrite(config_file, &params, 1);
3309
3310 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3311 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3312 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003313}
3314
3315//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.
3316INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3317{
3318 if (NULL == output)
3319 return RETURN_ERR;
3320 *output=100;
3321
3322 return RETURN_OK;
3323}
3324
3325//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.
3326INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3327{
3328 if (NULL == output)
3329 return RETURN_ERR;
3330 *output = -99;
3331
3332 return RETURN_OK;
3333}
3334
3335INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3336{
3337 return RETURN_ERR;
3338}
3339
3340
3341//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3342INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3343{
developerd946fd62022-12-08 18:03:28 +08003344 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003345 char cmd[MAX_BUF_SIZE]={'\0'};
3346 char buf[MAX_CMD_SIZE]={'\0'};
3347
3348 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3349 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003350 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003351
developerac6f1142022-12-20 19:26:35 +08003352 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003353 return RETURN_ERR;
3354 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer5f222492022-09-13 15:21:52 +08003355 _syscmd(cmd, buf, sizeof(buf));
3356 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003357
developer5f222492022-09-13 15:21:52 +08003358 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003359 return RETURN_OK;
3360}
3361
3362INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3363{
developer5f222492022-09-13 15:21:52 +08003364 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3365 struct params params={'\0'};
3366 char buf[MAX_BUF_SIZE] = {'\0'};
3367 char config_file[MAX_BUF_SIZE] = {'\0'};
3368
developer5b398df2022-11-17 20:39:48 +08003369 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3370 return RETURN_ERR;
3371
developer5f222492022-09-13 15:21:52 +08003372 params.name = "beacon_int";
3373 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3374 params.value = buf;
3375
3376 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3377 wifi_hostapdWrite(config_file, &params, 1);
3378
3379 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3381 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003382}
3383
3384//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.
3385INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3386{
developer06a01d92022-09-07 16:32:39 +08003387 //TODO: need to revisit below implementation
3388 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003389 char temp_output[128] = {0};
3390 char temp_TransmitRates[64] = {0};
3391 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003392
3393 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3394 if (NULL == output)
3395 return RETURN_ERR;
3396 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003397 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3398
3399 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3400 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3401 } else {
3402 temp = strtok(temp_TransmitRates," ");
3403 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003404 {
developere9d0abd2022-09-13 15:40:57 +08003405 // Convert 100 kbps to Mbps
3406 temp[strlen(temp)-1]=0;
3407 if((temp[0]=='5') && (temp[1]=='\0'))
3408 {
3409 temp="5.5";
3410 }
3411 strcat(temp_output,temp);
3412 temp = strtok(NULL," ");
3413 if(temp!=NULL)
3414 {
3415 strcat(temp_output,",");
3416 }
developer06a01d92022-09-07 16:32:39 +08003417 }
developere9d0abd2022-09-13 15:40:57 +08003418 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003419 }
developer06a01d92022-09-07 16:32:39 +08003420 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003421 return RETURN_OK;
3422}
3423
3424INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3425{
3426 char *temp;
3427 char temp1[128];
3428 char temp_output[128];
3429 char temp_TransmitRates[128];
3430 char set[128];
3431 char sub_set[128];
3432 int set_count=0,subset_count=0;
3433 int set_index=0,subset_index=0;
3434 char *token;
3435 int flag=0, i=0;
3436 struct params params={'\0'};
3437 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003438 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003439
3440 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3441 if(NULL == TransmitRates)
3442 return RETURN_ERR;
3443 strcpy(sub_set,TransmitRates);
3444
3445 //Allow only supported Data transmit rate to be set
3446 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3447 token = strtok(sub_set,",");
3448 while( token != NULL ) /* split the basic rate to be set, by comma */
3449 {
3450 sub_set[subset_count]=atoi(token);
3451 subset_count++;
3452 token=strtok(NULL,",");
3453 }
3454 token=strtok(set,",");
3455 while(token!=NULL) /* split the supported rate by comma */
3456 {
3457 set[set_count]=atoi(token);
3458 set_count++;
3459 token=strtok(NULL,",");
3460 }
3461 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3462 {
3463 for(set_index=0;set_index < set_count;set_index++)
3464 {
3465 flag=0;
3466 if(sub_set[subset_index]==set[set_index])
3467 break;
3468 else
3469 flag=1; /* No match found */
3470 }
3471 if(flag==1)
3472 return RETURN_ERR; //If value not found return Error
3473 }
3474 strcpy(temp_TransmitRates,TransmitRates);
3475
3476 for(i=0;i<strlen(temp_TransmitRates);i++)
3477 {
3478 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003479 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003480 {
3481 continue;
3482 }
3483 else
3484 {
3485 return RETURN_ERR;
3486 }
3487 }
3488 strcpy(temp_output,"");
3489 temp = strtok(temp_TransmitRates,",");
3490 while(temp!=NULL)
3491 {
3492 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003493 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003494 {
developeref938762022-10-19 17:21:01 +08003495 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003496 {
3497 return RETURN_ERR;
3498 }
3499 }
3500
3501 if(strcmp(temp,"5.5")==0)
3502 {
3503 strcpy(temp1,"55");
3504 }
3505 else
3506 {
3507 strcat(temp1,"0");
3508 }
3509 strcat(temp_output,temp1);
3510 temp = strtok(NULL,",");
3511 if(temp!=NULL)
3512 {
3513 strcat(temp_output," ");
3514 }
3515 }
3516 strcpy(TransmitRates,temp_output);
3517
3518 params.name= "basic_rates";
3519 params.value =TransmitRates;
3520
3521 wifi_dbg_printf("\n%s:",__func__);
3522 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3523 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3524 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3525 wifi_hostapdWrite(config_file,&params,1);
3526 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3527 return RETURN_OK;
3528}
3529
3530//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003531INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003532{
3533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3534 FILE *fp = NULL;
3535 char path[256] = {0}, output_string[256] = {0};
3536 int count = 0;
3537 char *interface = NULL;
3538
3539 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3540 if (fp == NULL)
3541 {
3542 printf("Failed to run command in Function %s\n", __FUNCTION__);
3543 return RETURN_ERR;
3544 }
3545 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3546 {
3547 interface = strchr(path, '=');
3548
3549 if (interface != NULL)
3550 {
3551 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003552 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003553 interface_name[count] = output_string[count];
3554
3555 interface_name[count] = '\0';
3556 }
3557 }
3558 pclose(fp);
3559 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3560 return RETURN_OK;
3561}
3562
3563INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3564{
3565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3566 output_struct->radio_BytesSent = 0;
3567 output_struct->radio_BytesReceived = 0;
3568 output_struct->radio_PacketsSent = 0;
3569 output_struct->radio_PacketsReceived = 0;
3570 output_struct->radio_ErrorsSent = 0;
3571 output_struct->radio_ErrorsReceived = 0;
3572 output_struct->radio_DiscardPacketsSent = 0;
3573 output_struct->radio_DiscardPacketsReceived = 0;
3574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3575 return RETURN_OK;
3576}
3577
3578
3579INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3580{
3581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer214b0592023-10-31 10:59:05 +08003582 CHAR buf[MAX_CMD_SIZE] = {0};
3583 CHAR Value[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08003584 FILE *fp = NULL;
3585
3586 if (ifname == NULL || strlen(ifname) <= 1)
3587 return RETURN_OK;
3588
developer214b0592023-10-31 10:59:05 +08003589 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
developer06a01d92022-09-07 16:32:39 +08003590 system(buf);
3591
3592 fp = fopen("/tmp/Radio_Stats.txt", "r");
3593 if(fp == NULL)
3594 {
3595 printf("/tmp/Radio_Stats.txt not exists \n");
3596 return RETURN_ERR;
3597 }
3598 fclose(fp);
3599
developer214b0592023-10-31 10:59:05 +08003600 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3601 File_Reading(buf, Value);
3602 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003603
developer214b0592023-10-31 10:59:05 +08003604 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3605 File_Reading(buf, Value);
3606 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003607
developer214b0592023-10-31 10:59:05 +08003608 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3609 File_Reading(buf, Value);
3610 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003611
developer214b0592023-10-31 10:59:05 +08003612 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3613 File_Reading(buf, Value);
3614 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003615
developer214b0592023-10-31 10:59:05 +08003616 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3617 File_Reading(buf, Value);
3618 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003619
developer214b0592023-10-31 10:59:05 +08003620 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3621 File_Reading(buf, Value);
3622 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003623
developer214b0592023-10-31 10:59:05 +08003624 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3625 File_Reading(buf, Value);
3626 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003627
developer214b0592023-10-31 10:59:05 +08003628 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3629 File_Reading(buf, Value);
3630 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003631
3632 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3633 return RETURN_OK;
3634}
3635
3636INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3637{
3638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3639 CHAR buf[MAX_CMD_SIZE] = {0};
3640 FILE *fp = NULL;
3641 INT count = 0;
3642
3643 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3644 {
3645 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3646 File_Reading(buf, status);
3647 }
3648 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3649 return RETURN_OK;
3650}
3651
3652//Get detail radio traffic static info
3653INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3654{
3655
3656#if 0
3657 //ifconfig radio_x
3658 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3659 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3660 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3661 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3662
3663 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3664 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3665 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.
3666 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.
3667
3668 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3669 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].
3670 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3671 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.
3672 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
3673 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
3674 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
3675 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
3676 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
3677
3678 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
3679 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
3680 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
3681 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.
3682
3683 return RETURN_OK;
3684#endif
3685
developera91d99f2022-09-29 15:59:10 +08003686 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003687 BOOL iface_status = FALSE;
3688 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer7c4c40e2023-10-25 10:17:04 +08003689 INT max_radio_num = 0, apIndex = 0;
developer06a01d92022-09-07 16:32:39 +08003690
3691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3692 if (NULL == output_struct)
3693 return RETURN_ERR;
3694
developer7c4c40e2023-10-25 10:17:04 +08003695 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08003696
developer7c4c40e2023-10-25 10:17:04 +08003697 memset(output_struct, 0, sizeof(wifi_radioTrafficStats2_t));
developer06a01d92022-09-07 16:32:39 +08003698
developer7c4c40e2023-10-25 10:17:04 +08003699 for(apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
3700 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3701 continue;
3702 wifi_getApEnable(radioIndex, &iface_status);
3703
3704 if (iface_status == TRUE)
3705 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3706 else
3707 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003708
developer7c4c40e2023-10-25 10:17:04 +08003709 output_struct->radio_BytesSent += radioTrafficStats.radio_BytesSent;
3710 output_struct->radio_BytesReceived += radioTrafficStats.radio_BytesReceived;
3711 output_struct->radio_PacketsSent += radioTrafficStats.radio_PacketsSent;
3712 output_struct->radio_PacketsReceived += radioTrafficStats.radio_PacketsReceived;
3713 output_struct->radio_ErrorsSent += radioTrafficStats.radio_ErrorsSent;
3714 output_struct->radio_ErrorsReceived += radioTrafficStats.radio_ErrorsReceived;
3715 output_struct->radio_DiscardPacketsSent += radioTrafficStats.radio_DiscardPacketsSent;
3716 output_struct->radio_DiscardPacketsReceived += radioTrafficStats.radio_DiscardPacketsReceived;
3717 }
developer06a01d92022-09-07 16:32:39 +08003718
3719 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3720 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].
3721 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3722 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.
3723 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
3724 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
3725 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
3726 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
3727 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
3728
3729 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
3730 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
3731 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
3732 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.
3733
3734 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3735
3736 return RETURN_OK;
3737}
3738
3739//Set radio traffic static Measureing rules
3740INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3741{
3742 //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
3743 // Else, save the MeasuringRate and MeasuringInterval for future usage
3744
3745 return RETURN_OK;
3746}
3747
3748//To start or stop RadioTrafficStats
3749INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3750{
3751 //zqiu: If the RadioTrafficStats process running
3752 // if(enable)
3753 // return RETURN_OK.
3754 // else
3755 // Stop RadioTrafficStats process
3756 // Else
3757 // if(enable)
3758 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3759 // else
3760 // return RETURN_OK.
3761
3762 return RETURN_OK;
3763}
3764
3765//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
3766INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3767{
3768 //zqiu: Please ignor signalIndex.
3769 if (NULL == SignalLevel)
3770 return RETURN_ERR;
3771 *SignalLevel=(radioIndex==0)?-19:-19;
3772
3773 return RETURN_OK;
3774}
3775
3776//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3777INT wifi_applyRadioSettings(INT radioIndex)
3778{
3779 return RETURN_OK;
3780}
3781
3782//Get the radio index assocated with this SSID entry
3783INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3784{
developer5b398df2022-11-17 20:39:48 +08003785 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003786 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003787 int max_radio_num = 0;
3788 wifi_getMaxRadioNumber(&max_radio_num);
3789 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003790 return RETURN_OK;
3791}
3792
3793//Device.WiFi.SSID.{i}.Enable
3794//Get SSID enable configuration parameters (not the SSID enable status)
3795INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3796{
3797 if (NULL == output_bool)
3798 return RETURN_ERR;
3799
developer06a01d92022-09-07 16:32:39 +08003800 return wifi_getApEnable(ssidIndex, output_bool);
3801}
3802
3803//Device.WiFi.SSID.{i}.Enable
3804//Set SSID enable configuration parameters
3805INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3806{
developer06a01d92022-09-07 16:32:39 +08003807 return wifi_setApEnable(ssidIndex, enable);
3808}
3809
3810//Device.WiFi.SSID.{i}.Status
3811//Get the SSID enable status
3812INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3813{
3814 char cmd[MAX_CMD_SIZE]={0};
3815 char buf[MAX_BUF_SIZE]={0};
3816 BOOL output_bool;
3817
3818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3819 if (NULL == output_string)
3820 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003821
developer06a01d92022-09-07 16:32:39 +08003822 wifi_getApEnable(ssidIndex,&output_bool);
3823 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3824
3825 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3826 return RETURN_OK;
3827}
3828
3829// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3830INT wifi_getSSIDName(INT apIndex, CHAR *output)
3831{
3832 char config_file[MAX_BUF_SIZE] = {0};
3833
3834 if (NULL == output)
3835 return RETURN_ERR;
3836
developerefb790a2023-12-26 18:58:32 +08003837 if (!syn_flag) {
3838 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3839 wifi_hostapdRead(config_file,"ssid",output,32);
3840 } else
developer07ded1f2024-01-10 10:30:15 +08003841 snprintf(output, 32, "%s", vap_info[apIndex].ssid);
developer06a01d92022-09-07 16:32:39 +08003842
3843 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3844 return RETURN_OK;
3845}
3846
3847// Set a max 32 byte string and sets an internal variable to the SSID name
3848INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3849{
3850 char str[MAX_BUF_SIZE]={'\0'};
3851 char cmd[MAX_CMD_SIZE]={'\0'};
3852 struct params params;
3853 char config_file[MAX_BUF_SIZE] = {0};
3854
3855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003856 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003857 return RETURN_ERR;
3858
3859 params.name = "ssid";
3860 params.value = ssid_string;
3861 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3862 wifi_hostapdWrite(config_file, &params, 1);
3863 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3864 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3865
3866 return RETURN_OK;
3867}
3868
3869//Get the BSSID
3870INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3871{
3872 char cmd[MAX_CMD_SIZE]="";
3873
3874 if (NULL == output_string)
3875 return RETURN_ERR;
3876
3877 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3878 {
developer1d57d002022-10-12 18:03:15 +08003879 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep bssid | cut -d '=' -f2 | tr -d '\n'", CONFIG_PREFIX, ssidIndex);
developer06a01d92022-09-07 16:32:39 +08003880 _syscmd(cmd, output_string, 64);
3881 return RETURN_OK;
3882 }
3883 strncpy(output_string, "\0", 1);
3884
3885 return RETURN_ERR;
3886}
3887
3888//Get the MAC address associated with this Wifi SSID
3889INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3890{
3891 wifi_getBaseBSSID(ssidIndex,output_string);
3892 return RETURN_OK;
3893}
3894
3895//Get the basic SSID traffic static info
3896//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3897//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3898INT wifi_applySSIDSettings(INT ssidIndex)
3899{
developerd946fd62022-12-08 18:03:28 +08003900 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003901 BOOL status = false;
3902 char cmd[MAX_CMD_SIZE] = {0};
3903 char buf[MAX_CMD_SIZE] = {0};
3904 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003905 int max_radio_num = 0;
3906 int radioIndex = 0;
3907
3908 wifi_getMaxRadioNumber(&max_radio_num);
3909
3910 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003911
3912 wifi_getApEnable(ssidIndex,&status);
3913 // Do not apply when ssid index is disabled
3914 if (status == false)
3915 return RETURN_OK;
3916
3917 /* Doing full remove and add for ssid Index
3918 * Not all hostapd options are supported with reload
3919 * for example macaddr_acl
3920 */
3921 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3922 return RETURN_ERR;
3923
3924 ret = wifi_setApEnable(ssidIndex,true);
3925
3926 /* Workaround for hostapd issue with multiple bss definitions
3927 * when first created interface will be removed
3928 * then all vaps other vaps on same phy are removed
3929 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003930 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003931 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003932 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003933 continue;
developer643b28f2023-04-04 10:26:01 +08003934 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003935 _syscmd(cmd, buf, sizeof(buf));
3936 if(*buf == '1')
3937 wifi_setApEnable(apIndex, true);
3938 }
3939
3940 return ret;
3941}
3942
developera3c68b92022-09-13 15:27:29 +08003943struct channels_noise {
3944 int channel;
3945 int noise;
3946};
3947
3948// Return noise array for each channel
3949int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3950{
developerd946fd62022-12-08 18:03:28 +08003951 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003952 FILE *f = NULL;
3953 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003954 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003955 size_t len = 0;
3956 ssize_t read = 0;
3957 int tmp = 0, arr_index = -1;
3958
developerac6f1142022-12-20 19:26:35 +08003959 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003960 return RETURN_ERR;
3961 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003962
3963 if ((f = popen(cmd, "r")) == NULL) {
3964 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3965 return RETURN_ERR;
3966 }
developer5550e242022-09-30 09:59:32 +08003967
3968 while(fgets(line, sizeof(line), f) != NULL) {
3969 if(arr_index < channels_num){
3970 sscanf(line, "%d", &tmp);
3971 if (tmp > 0) { // channel frequency, the first line must be frequency
3972 arr_index++;
3973 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3974 } else { // noise
3975 channels_noise_arr[arr_index].noise = tmp;
3976 }
3977 }else{
3978 break;
developera3c68b92022-09-13 15:27:29 +08003979 }
3980 }
developera3c68b92022-09-13 15:27:29 +08003981 pclose(f);
3982 return RETURN_OK;
3983}
3984
developer06a01d92022-09-07 16:32:39 +08003985//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3986//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3987INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3988{
developera3c68b92022-09-13 15:27:29 +08003989 int index = -1;
3990 wifi_neighbor_ap2_t *scan_array = NULL;
3991 char cmd[256]={0};
3992 char buf[128]={0};
3993 char file_name[32] = {0};
3994 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003995 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003996 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003997 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003998 int freq=0;
3999 FILE *f = NULL;
4000 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08004001 int channels_num = 0;
4002 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08004003 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08004004 bool filter_enable = false;
4005 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08004006 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004007
developer615510b2022-09-27 10:14:35 +08004008 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004009
developerac6f1142022-12-20 19:26:35 +08004010 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004011 return RETURN_ERR;
4012
developera3c68b92022-09-13 15:27:29 +08004013 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4014 f = fopen(file_name, "r");
4015 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08004016 fgets(buf, sizeof(file_name), f);
4017 if ((strncmp(buf, "0", 1)) != 0) {
4018 fgets(filter_SSID, sizeof(file_name), f);
4019 if (strlen(filter_SSID) != 0)
4020 filter_enable = true;
4021 }
developera3c68b92022-09-13 15:27:29 +08004022 fclose(f);
4023 }
4024
developer033b37b2022-10-18 11:27:46 +08004025 phyId = radio_index_to_phy(radioIndex);
4026 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08004027 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08004028 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004029
developer5550e242022-09-30 09:59:32 +08004030
developer06a01d92022-09-07 16:32:39 +08004031
developerd946fd62022-12-08 18:03:28 +08004032 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4033 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
developera3c68b92022-09-13 15:27:29 +08004034 fprintf(stderr, "cmd: %s\n", cmd);
4035 if ((f = popen(cmd, "r")) == NULL) {
4036 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4037 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004038 }
developer5550e242022-09-30 09:59:32 +08004039
4040 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4041 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
4042
developer615510b2022-09-27 10:14:35 +08004043 ret = fgets(line, sizeof(line), f);
4044 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08004045 if(strstr(line, "BSS") != NULL) { // new neighbor info
4046 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
4047 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4048 // 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 +08004049
developera3c68b92022-09-13 15:27:29 +08004050 if (!filter_BSS) {
4051 index++;
4052 wifi_neighbor_ap2_t *tmp;
4053 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4054 if (tmp == NULL) { // no more memory to use
4055 index--;
4056 wifi_dbg_printf("%s: realloc failed\n", __func__);
4057 break;
4058 }
4059 scan_array = tmp;
4060 }
4061 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4062
4063 filter_BSS = false;
4064 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4065 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4066 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4067 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4068 } else if (strstr(line, "freq") != NULL) {
4069 sscanf(line," freq: %d", &freq);
4070 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4071
4072 if (freq >= 2412 && freq <= 2484) {
4073 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4074 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4075 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4076 }
4077 else if (freq >= 5160 && freq <= 5805) {
4078 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4079 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4080 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4081 }
4082
4083 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08004084 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08004085 for (int i = 0; i < channels_num; i++) {
4086 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4087 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4088 break;
4089 }
4090 }
4091 }
4092 } else if (strstr(line, "beacon interval") != NULL) {
4093 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4094 } else if (strstr(line, "signal") != NULL) {
4095 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4096 } else if (strstr(line,"SSID") != NULL) {
4097 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4098 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4099 filter_BSS = true;
4100 }
4101 } else if (strstr(line, "Supported rates") != NULL) {
4102 char SRate[80] = {0}, *tmp = NULL;
4103 memset(buf, 0, sizeof(buf));
4104 strcpy(SRate, line);
4105 tmp = strtok(SRate, ":");
4106 tmp = strtok(NULL, ":");
4107 strcpy(buf, tmp);
4108 memset(SRate, 0, sizeof(SRate));
4109
4110 tmp = strtok(buf, " \n");
4111 while (tmp != NULL) {
4112 strcat(SRate, tmp);
4113 if (SRate[strlen(SRate) - 1] == '*') {
4114 SRate[strlen(SRate) - 1] = '\0';
4115 }
4116 strcat(SRate, ",");
4117
4118 tmp = strtok(NULL, " \n");
4119 }
4120 SRate[strlen(SRate) - 1] = '\0';
4121 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4122 } else if (strstr(line, "DTIM") != NULL) {
4123 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4124 } else if (strstr(line, "VHT capabilities") != NULL) {
4125 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4126 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4127 } else if (strstr(line, "HT capabilities") != NULL) {
4128 strcat(scan_array[index].ap_SupportedStandards, ",n");
4129 strcpy(scan_array[index].ap_OperatingStandards, "n");
4130 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004131 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004132 sscanf(line," * channel width: %d", &vht_channel_width);
4133 if(vht_channel_width == 1) {
4134 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4135 } else {
4136 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4137 }
4138 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4139 continue;
4140 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004141 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004142 sscanf(line," * secondary channel offset: %s", &buf);
4143 if (!strcmp(buf, "above")) {
4144 //40Mhz +
4145 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4146 }
4147 else if (!strcmp(buf, "below")) {
4148 //40Mhz -
4149 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4150 } else {
4151 //20Mhz
4152 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4153 }
4154 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4155 continue;
4156 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004157 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4158 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4159 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004160 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4161 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004162 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004163 else
developer615510b2022-09-27 10:14:35 +08004164 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004165 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004166 if (strstr(line, "HE80/5GHz") != NULL) {
4167 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4168 ret = fgets(line, sizeof(line), f);
4169 } else
4170 continue;
developera3c68b92022-09-13 15:27:29 +08004171 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004172 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004173 }
developer615510b2022-09-27 10:14:35 +08004174 continue;
developera3c68b92022-09-13 15:27:29 +08004175 } else if (strstr(line, "WPA") != NULL) {
4176 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4177 } else if (strstr(line, "RSN") != NULL) {
4178 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4179 } else if (strstr(line, "Group cipher") != NULL) {
4180 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4181 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4182 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4183 }
4184 }
developer615510b2022-09-27 10:14:35 +08004185 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004186 }
4187
4188 if (!filter_BSS) {
4189 *output_array_size = index + 1;
4190 } else {
4191 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4192 *output_array_size = index;
4193 }
4194 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004195 pclose(f);
developer5550e242022-09-30 09:59:32 +08004196 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004197 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004198 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004199}
4200
4201//>> Deprecated: used for old RDKB code.
4202INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4203{
4204 INT status = RETURN_ERR;
4205
4206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4207 output_struct->wifi_PLCPErrorCount = 0;
4208 output_struct->wifi_FCSErrorCount = 0;
4209 output_struct->wifi_InvalidMACCount = 0;
4210 output_struct->wifi_PacketsOtherReceived = 0;
4211 output_struct->wifi_Noise = 0;
4212 status = RETURN_OK;
4213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4214 return status;
4215}
4216
4217INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4218{
developerd946fd62022-12-08 18:03:28 +08004219 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004220 char cmd[128] = {0};
4221 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004222 char *pos = NULL;
4223
4224 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4225 if (NULL == output_struct)
4226 return RETURN_ERR;
4227
developerac6f1142022-12-20 19:26:35 +08004228 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004229 return RETURN_ERR;
4230
developer06a01d92022-09-07 16:32:39 +08004231 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4232
developerd946fd62022-12-08 18:03:28 +08004233 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004234 _syscmd(cmd, buf, sizeof(buf));
4235
4236 pos = buf;
4237 if ((pos = strstr(pos, "RX packets:")) == NULL)
4238 return RETURN_ERR;
4239 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4240
4241 if ((pos = strstr(pos, "TX packets:")) == NULL)
4242 return RETURN_ERR;
4243 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4244
4245 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4246 return RETURN_ERR;
4247 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4248
4249 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4250 return RETURN_ERR;
4251 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4252
developerd946fd62022-12-08 18:03:28 +08004253 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004254 _syscmd(cmd, buf, sizeof(buf));
4255 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4256
4257#if 0
4258 //TODO: need to revisit below implementation
4259 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4260 char interface_name[MAX_BUF_SIZE] = {0};
4261 char interface_status[MAX_BUF_SIZE] = {0};
4262 char Value[MAX_BUF_SIZE] = {0};
4263 char buf[MAX_CMD_SIZE] = {0};
4264 char cmd[MAX_CMD_SIZE] = {0};
4265 FILE *fp = NULL;
4266
4267 if (NULL == output_struct) {
4268 return RETURN_ERR;
4269 }
4270
4271 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4272
4273 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4274 {
4275 if(apIndex == 0) //private_wifi for 2.4G
4276 {
developerac6f1142022-12-20 19:26:35 +08004277 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004278 }
4279 else if(apIndex == 1) //private_wifi for 5G
4280 {
developerac6f1142022-12-20 19:26:35 +08004281 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004282 }
4283 else if(apIndex == 4) //public_wifi for 2.4G
4284 {
4285 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4286 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4287 {
4288 return RETURN_ERR;
4289 }
4290 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004291 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004292 else//tenda
developerac6f1142022-12-20 19:26:35 +08004293 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004294 }
4295 else if(apIndex == 5) //public_wifi for 5G
4296 {
developerac6f1142022-12-20 19:26:35 +08004297 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004298 }
4299
4300 GetIfacestatus(interface_name, interface_status);
4301
4302 if(0 != strcmp(interface_status, "1"))
4303 return RETURN_ERR;
4304
4305 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4306 system(cmd);
4307
4308 fp = fopen("/tmp/SSID_Stats.txt", "r");
4309 if(fp == NULL)
4310 {
4311 printf("/tmp/SSID_Stats.txt not exists \n");
4312 return RETURN_ERR;
4313 }
4314 fclose(fp);
4315
4316 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4317 File_Reading(buf, Value);
4318 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4319
4320 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4321 File_Reading(buf, Value);
4322 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4323
4324 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4325 File_Reading(buf, Value);
4326 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4327
4328 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4329 File_Reading(buf, Value);
4330 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4331
4332 /* There is no specific parameter from caller to associate the value wifi_Associations */
4333 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4334 //_syscmd(cmd, buf, sizeof(buf));
4335 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4336 }
4337#endif
4338 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4339 return RETURN_OK;
4340}
4341
4342INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4343{
4344 char interface_name[MAX_BUF_SIZE] = {0};
4345 char interface_status[MAX_BUF_SIZE] = {0};
4346 char Value[MAX_BUF_SIZE] = {0};
4347 char buf[MAX_CMD_SIZE] = {0};
4348 char cmd[MAX_CMD_SIZE] = {0};
4349 FILE *fp = NULL;
4350
4351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4352 if (NULL == output_struct)
4353 return RETURN_ERR;
4354
4355 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4356
developerac6f1142022-12-20 19:26:35 +08004357 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004358 return RETURN_ERR;
4359 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004360
developerd946fd62022-12-08 18:03:28 +08004361 if(0 != strcmp(interface_status, "1"))
4362 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004363
developerd946fd62022-12-08 18:03:28 +08004364 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4365 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004366
developerd946fd62022-12-08 18:03:28 +08004367 fp = fopen("/tmp/SSID_Stats.txt", "r");
4368 if(fp == NULL)
4369 {
4370 printf("/tmp/SSID_Stats.txt not exists \n");
4371 return RETURN_ERR;
4372 }
4373 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004374
developerd946fd62022-12-08 18:03:28 +08004375 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4376 File_Reading(buf, Value);
4377 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004378
developerd946fd62022-12-08 18:03:28 +08004379 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4380 File_Reading(buf, Value);
4381 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004382
developerd946fd62022-12-08 18:03:28 +08004383 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4384 File_Reading(buf, Value);
4385 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004386
developerd946fd62022-12-08 18:03:28 +08004387 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4388 File_Reading(buf, Value);
4389 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004390
4391 output_struct->wifi_UnicastPacketsSent = 0;
4392 output_struct->wifi_UnicastPacketsReceived = 0;
4393 output_struct->wifi_MulticastPacketsSent = 0;
4394 output_struct->wifi_MulticastPacketsReceived = 0;
4395 output_struct->wifi_BroadcastPacketsSent = 0;
4396 output_struct->wifi_BroadcastPacketsRecevied = 0;
4397 output_struct->wifi_UnknownPacketsReceived = 0;
4398
4399 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4400 return RETURN_OK;
4401}
4402
4403INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4404{
4405 INT status = RETURN_ERR;
4406
4407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4408 //Below values should get updated from hal
4409 output_struct->wifi_RetransCount=0;
4410 output_struct->wifi_FailedRetransCount=0;
4411 output_struct->wifi_RetryCount=0;
4412 output_struct->wifi_MultipleRetryCount=0;
4413 output_struct->wifi_ACKFailureCount=0;
4414 output_struct->wifi_AggregatedPacketCount=0;
4415
4416 status = RETURN_OK;
4417 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4418
4419 return status;
4420}
4421
4422INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4423{
4424 INT status = RETURN_ERR;
4425 UINT index;
4426 wifi_neighbor_ap_t *pt=NULL;
4427
4428 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4429 *output_array_size=2;
4430 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4431 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4432 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4433 strcpy(pt->ap_Radio,"");
4434 strcpy(pt->ap_SSID,"");
4435 strcpy(pt->ap_BSSID,"");
4436 strcpy(pt->ap_Mode,"");
4437 pt->ap_Channel=1;
4438 pt->ap_SignalStrength=0;
4439 strcpy(pt->ap_SecurityModeEnabled,"");
4440 strcpy(pt->ap_EncryptionMode,"");
4441 strcpy(pt->ap_OperatingFrequencyBand,"");
4442 strcpy(pt->ap_SupportedStandards,"");
4443 strcpy(pt->ap_OperatingStandards,"");
4444 strcpy(pt->ap_OperatingChannelBandwidth,"");
4445 pt->ap_BeaconPeriod=1;
4446 pt->ap_Noise=0;
4447 strcpy(pt->ap_BasicDataTransferRates,"");
4448 strcpy(pt->ap_SupportedDataTransferRates,"");
4449 pt->ap_DTIMPeriod=1;
4450 pt->ap_ChannelUtilization = 1;
4451 }
4452
4453 status = RETURN_OK;
4454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4455
4456 return status;
4457}
4458
4459//----------------- AP HAL -------------------------------
4460
4461//>> Deprecated: used for old RDKB code.
4462INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4463{
4464 if (NULL == output_ulong || NULL == output_struct)
4465 return RETURN_ERR;
4466 *output_ulong = 0;
4467 *output_struct = NULL;
4468 return RETURN_OK;
4469}
4470
4471#ifdef HAL_NETLINK_IMPL
4472static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4473 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4474 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4475 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4476 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4477 char mac_addr[20];
4478 static int count=0;
4479 int rate=0;
4480
4481 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4482
4483 nla_parse(tb,
4484 NL80211_ATTR_MAX,
4485 genlmsg_attrdata(gnlh, 0),
4486 genlmsg_attrlen(gnlh, 0),
4487 NULL);
4488
4489 if(!tb[NL80211_ATTR_STA_INFO]) {
4490 fprintf(stderr, "sta stats missing!\n");
4491 return NL_SKIP;
4492 }
4493
4494
4495 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4496 fprintf(stderr, "failed to parse nested attributes!\n");
4497 return NL_SKIP;
4498 }
4499
4500 //devIndex starts from 1
4501 if( ++count == out->wifi_devIndex )
4502 {
4503 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4504 //Getting the mac addrress
4505 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4506
4507 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4508 fprintf(stderr, "failed to parse nested rate attributes!");
4509 return NL_SKIP;
4510 }
4511
4512 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4513 if(rinfo[NL80211_RATE_INFO_BITRATE])
4514 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4515 out->wifi_devTxRate = rate/10;
4516 }
4517
4518 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4519 fprintf(stderr, "failed to parse nested rate attributes!");
4520 return NL_SKIP;
4521 }
4522
4523 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4524 if(rinfo[NL80211_RATE_INFO_BITRATE])
4525 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4526 out->wifi_devRxRate = rate/10;
4527 }
4528 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4529 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4530
4531 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4532 count = 0; //starts the count for next cycle
4533 return NL_STOP;
4534 }
4535
4536 return NL_SKIP;
4537
4538}
4539#endif
4540
4541INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4542{
4543#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004544 Netlink nl = {0};
4545 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004546 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004547
developer30423732022-12-01 16:17:49 +08004548 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004549 info.wifi_devIndex = devIndex;
4550
developerac6f1142022-12-20 19:26:35 +08004551 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004552 return RETURN_ERR;
4553
4554 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004555
4556 nl.id = initSock80211(&nl);
4557
4558 if (nl.id < 0) {
4559 fprintf(stderr, "Error initializing netlink \n");
4560 return -1;
4561 }
4562
4563 struct nl_msg* msg = nlmsg_alloc();
4564
4565 if (!msg) {
4566 fprintf(stderr, "Failed to allocate netlink message.\n");
4567 nlfree(&nl);
4568 return -2;
4569 }
4570
4571 genlmsg_put(msg,
4572 NL_AUTO_PORT,
4573 NL_AUTO_SEQ,
4574 nl.id,
4575 0,
4576 NLM_F_DUMP,
4577 NL80211_CMD_GET_STATION,
4578 0);
4579
4580 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4581 nl_send_auto(nl.socket, msg);
4582 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4583 nl_recvmsgs(nl.socket, nl.cb);
4584 nlmsg_free(msg);
4585 nlfree(&nl);
4586
4587 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4588 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4589 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4590 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4591 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4592 return RETURN_OK;
4593#else
4594 //iw utility to retrieve station information
4595#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4596#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4597#define MACFILE "/tmp/wifi_AssoMac.txt"
4598#define TXRATEFILE "/tmp/wifi_txrate.txt"
4599#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4600 FILE *file = NULL;
4601 char if_name[10] = {'\0'};
4602 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004603 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004604 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004605 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004606
developerac6f1142022-12-20 19:26:35 +08004607 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004608 return RETURN_ERR;
4609
4610 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004611
4612 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4613 file = popen(pipeCmd, "r");
4614
4615 if(file == NULL)
4616 return RETURN_ERR; //popen failed
4617
4618 fgets(line, sizeof line, file);
4619 device = atoi(line);
4620 pclose(file);
4621
4622 if(device == 0)
4623 return RETURN_ERR; //No devices are connected
4624
4625 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4626 system(pipeCmd);
4627
4628 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4629
4630 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4631
4632 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4633
4634 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4635
4636 //devIndex starts from 1, ++count
4637 if((file = fopen(SIGNALFILE, "r")) != NULL )
4638 {
4639 for(count =0;fgets(line, sizeof line, file) != NULL;)
4640 {
4641 if (++count == devIndex)
4642 {
4643 output_struct->wifi_devSignalStrength = atoi(line);
4644 break;
4645 }
4646 }
4647 fclose(file);
4648 }
4649 else
4650 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4651
4652 if((file = fopen(MACFILE, "r")) != NULL )
4653 {
4654 for(count =0;fgets(line, sizeof line, file) != NULL;)
4655 {
4656 if (++count == devIndex)
4657 {
4658 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]);
4659 break;
4660 }
4661 }
4662 fclose(file);
4663 }
4664 else
4665 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4666
4667 if((file = fopen(TXRATEFILE, "r")) != NULL )
4668 {
4669 for(count =0;fgets(line, sizeof line, file) != NULL;)
4670 {
4671 if (++count == devIndex)
4672 {
4673 output_struct->wifi_devTxRate = atoi(line);
4674 break;
4675 }
4676 }
4677 fclose(file);
4678 }
4679 else
4680 fprintf(stderr,"fopen wifi_txrate.txt failed");
4681
4682 if((file = fopen(RXRATEFILE, "r")) != NULL)
4683 {
4684 for(count =0;fgets(line, sizeof line, file) != NULL;)
4685 {
4686 if (++count == devIndex)
4687 {
4688 output_struct->wifi_devRxRate = atoi(line);
4689 break;
4690 }
4691 }
4692 fclose(file);
4693 }
4694 else
4695 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4696
4697 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4698
4699 return RETURN_OK;
4700#endif
4701}
4702
4703INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4704{
4705 if (NULL == device)
4706 return RETURN_ERR;
4707 return RETURN_OK;
4708}
4709//<<
4710
4711
4712//--------------wifi_ap_hal-----------------------------
4713//enables CTS protection for the radio used by this AP
4714INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4715{
4716 //save config and Apply instantly
4717 return RETURN_ERR;
4718}
4719
4720// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4721INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4722{
developer463d39a2022-09-13 15:32:51 +08004723 char config_file[64] = {'\0'};
4724 char buf[64] = {'\0'};
4725 struct params list;
4726
4727 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4728 list.name = "ht_coex";
4729 snprintf(buf, sizeof(buf), "%d", enable);
4730 list.value = buf;
4731
4732 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4733 wifi_hostapdWrite(config_file, &list, 1);
4734 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4735
4736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4737
4738 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004739}
4740
4741//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4742INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4743{
developerea4bcce2022-09-13 15:26:13 +08004744 char config_file[MAX_BUF_SIZE] = {'\0'};
4745 char buf[MAX_BUF_SIZE] = {'\0'};
4746 struct params list;
4747
4748 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4749 if (threshold < 256 || threshold > 2346 )
4750 return RETURN_ERR;
4751 list.name = "fragm_threshold";
4752 snprintf(buf, sizeof(buf), "%d", threshold);
4753 list.value = buf;
4754
4755 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4756 wifi_hostapdWrite(config_file, &list, 1);
4757 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004758
developerea4bcce2022-09-13 15:26:13 +08004759 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004760
4761 return RETURN_OK;
4762}
4763
4764// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4765INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4766{
developer51a927d2022-09-13 15:42:22 +08004767 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004768 char cmd[512] = {'\0'};
4769 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004770 char stbc_config[16] = {'\0'};
4771 wifi_band band;
4772 int iterator = 0;
4773 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004774 int ant_count = 0;
4775 int ant_bitmap = 0;
4776 struct params list;
developer51a927d2022-09-13 15:42:22 +08004777
4778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4779
4780 band = wifi_index_to_band(radioIndex);
4781 if (band == band_invalid)
4782 return RETURN_ERR;
4783
4784 if (band == band_2_4)
4785 iterator = 1;
4786 else if (band == band_5)
4787 iterator = 2;
4788 else
4789 return RETURN_OK;
4790
developer110b8a32022-12-26 15:56:44 +08004791 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4792 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4793 ant_count += ant_bitmap & 1;
4794
4795 if (ant_count == 1 && STBC_Enable == TRUE) {
4796 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4797 return RETURN_OK;
4798 }
4799
developer51a927d2022-09-13 15:42:22 +08004800 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4801
4802 // set ht and vht config
4803 for (int i = 0; i < iterator; i++) {
4804 memset(stbc_config, 0, sizeof(stbc_config));
4805 memset(cmd, 0, sizeof(cmd));
4806 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004807 list.name = (i == 0)?"ht_capab":"vht_capab";
4808 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004809 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4810 _syscmd(cmd, buf, sizeof(buf));
4811 if (strlen(buf) != 0)
4812 current_stbc = TRUE;
4813 if (current_stbc == STBC_Enable)
4814 continue;
4815
4816 if (STBC_Enable == TRUE) {
4817 // Append the STBC flags in capab config
4818 memset(cmd, 0, sizeof(cmd));
4819 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004820 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004821 else
developer6372c2b2022-10-27 17:39:51 +08004822 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004823 _syscmd(cmd, buf, sizeof(buf));
4824 } else if (STBC_Enable == FALSE) {
4825 // Remove the STBC flags and remain other flags in capab
4826 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004827 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004828 _syscmd(cmd, buf, sizeof(buf));
4829 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004830 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004831 _syscmd(cmd, buf, sizeof(buf));
4832 }
developer110b8a32022-12-26 15:56:44 +08004833 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4834 list.value = buf;
4835 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004836 }
4837
4838 wifi_reloadAp(radioIndex);
4839
4840 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4841 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004842}
4843
4844// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4845INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4846{
developerfe7aefc2022-12-23 17:13:37 +08004847 char cmd[128] = {0};
4848 char buf[128] = {0};
4849 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004850
4851 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4852
4853 if(output_bool == NULL)
4854 return RETURN_ERR;
4855
developerfe7aefc2022-12-23 17:13:37 +08004856 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4857 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004858
developerfe7aefc2022-12-23 17:13:37 +08004859 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4860 _syscmd(cmd, buf, sizeof(buf));
4861
4862 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004863 *output_bool = TRUE;
4864 else
4865 *output_bool = FALSE;
4866
4867 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4868 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004869}
4870
4871// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4872INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4873{
developerfe7aefc2022-12-23 17:13:37 +08004874 char config_file[128] = {0};
4875 struct params list = {0};
4876 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004877
4878 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4879
developerfe7aefc2022-12-23 17:13:37 +08004880 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004881 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004882
developerfe7aefc2022-12-23 17:13:37 +08004883 if (amsduEnable == enable)
4884 return RETURN_OK;
4885
4886 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4887 list.name = "amsdu";
4888 list.value = amsduEnable? "1":"0";
4889 wifi_hostapdWrite(config_file, &list, 1);
4890 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4891 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004892
4893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4894 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004895}
4896
4897//P2 // outputs the number of Tx streams
4898INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4899{
developer2de97692022-09-26 14:00:03 +08004900 char buf[8] = {0};
4901 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004902 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004903
4904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4905
developer033b37b2022-10-18 11:27:46 +08004906 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004907 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004908 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004909
developer110b8a32022-12-26 15:56:44 +08004910 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004911
4912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4913
4914 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004915}
4916
developer110b8a32022-12-26 15:56:44 +08004917INT fitChainMask(INT radioIndex, int antcount)
4918{
4919 char buf[128] = {0};
4920 char cmd[128] = {0};
4921 char config_file[64] = {0};
4922 wifi_band band;
4923 struct params list[2] = {0};
4924
4925 band = wifi_index_to_band(radioIndex);
4926 if (band == band_invalid)
4927 return RETURN_ERR;
4928
4929 list[0].name = "he_mu_beamformer";
4930 list[1].name = "he_su_beamformer";
4931
4932 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4933 if (antcount == 1) {
4934 // remove config about multiple antennas
4935 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4936 _syscmd(cmd, buf, sizeof(buf));
4937
4938 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4939 _syscmd(cmd, buf, sizeof(buf));
4940
4941 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4942 _syscmd(cmd, buf, sizeof(buf));
4943
4944 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4945 _syscmd(cmd, buf, sizeof(buf));
4946
4947 list[0].value = "0";
4948 list[1].value = "0";
4949 } else {
4950 // If we only set RX STBC means STBC is enable and TX STBC is disable when last time set one antenna. so we need to add it back.
4951 if (band == band_2_4 || band == band_5) {
4952 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4953 _syscmd(cmd, buf, sizeof(buf));
4954 if (strlen(buf) > 0) {
4955 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4956 _syscmd(cmd, buf, sizeof(buf));
4957 }
4958 }
4959 if (band == band_5) {
4960 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4961 _syscmd(cmd, buf, sizeof(buf));
4962 if (strlen(buf) > 0) {
4963 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4964 _syscmd(cmd, buf, sizeof(buf));
4965 }
4966 }
4967
4968 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4969 _syscmd(cmd, buf, sizeof(buf));
4970 if (strlen(buf) == 0) {
4971 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4972 _syscmd(cmd, buf, sizeof(buf));
4973 }
4974
4975 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4976 _syscmd(cmd, buf, sizeof(buf));
4977 if (strlen(buf) == 0) {
4978 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4979 _syscmd(cmd, buf, sizeof(buf));
4980 }
4981
4982 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4983 _syscmd(cmd, buf, sizeof(buf));
4984 if (strlen(buf) == 0) {
4985 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4986 } else {
4987 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4988 }
4989 _syscmd(cmd, buf, sizeof(buf));
4990
4991 list[0].value = "1";
4992 list[1].value = "1";
4993 }
4994 wifi_hostapdWrite(config_file, list, 2);
4995}
4996
developer06a01d92022-09-07 16:32:39 +08004997//P2 // sets the number of Tx streams to an enviornment variable
4998INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4999{
developer2de97692022-09-26 14:00:03 +08005000 char cmd[128] = {0};
5001 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08005002 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08005003 int cur_mask = 0;
5004 int antcount = 0;
5005 wifi_band band;
developer2de97692022-09-26 14:00:03 +08005006
5007 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5008
developer110b8a32022-12-26 15:56:44 +08005009 if (numStreams <= 0) {
5010 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08005011 return RETURN_ERR;
5012 }
developer110b8a32022-12-26 15:56:44 +08005013
5014 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
5015 if (cur_mask == numStreams)
5016 return RETURN_OK;
5017
developer2de97692022-09-26 14:00:03 +08005018 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08005019
5020 phyId = radio_index_to_phy(radioIndex);
5021 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08005022 _syscmd(cmd, buf, sizeof(buf));
5023
5024 if (strlen(buf) > 0) {
5025 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5026 return RETURN_ERR;
5027 }
developer2de97692022-09-26 14:00:03 +08005028
developer110b8a32022-12-26 15:56:44 +08005029 // if chain mask changed, we need to make the hostapd config valid.
5030 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5031 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08005032 }
developer110b8a32022-12-26 15:56:44 +08005033 fitChainMask(radioIndex, antcount);
5034
5035 wifi_setRadioEnable(radioIndex, TRUE);
5036
developer2de97692022-09-26 14:00:03 +08005037 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5038 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005039}
5040
5041//P2 // outputs the number of Rx streams
5042INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5043{
developer110b8a32022-12-26 15:56:44 +08005044 char buf[8] = {0};
5045 char cmd[128] = {0};
5046 int phyId = 0;
5047
developer2de97692022-09-26 14:00:03 +08005048 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005049
5050 phyId = radio_index_to_phy(radioIndex);
5051 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5052 _syscmd(cmd, buf, sizeof(buf));
5053
5054 *output_int = (INT)strtol(buf, NULL, 16);
5055
developer2de97692022-09-26 14:00:03 +08005056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005057
developer06a01d92022-09-07 16:32:39 +08005058 return RETURN_OK;
5059}
5060
5061//P2 // sets the number of Rx streams to an enviornment variable
5062INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5063{
developer2de97692022-09-26 14:00:03 +08005064 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5065 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5066 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5067 return RETURN_ERR;
5068 }
5069 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005070 return RETURN_ERR;
5071}
5072
5073//Get radio RDG enable setting
5074INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5075{
5076 if (NULL == output_bool)
5077 return RETURN_ERR;
5078 *output_bool = TRUE;
5079 return RETURN_OK;
5080}
5081
5082//Get radio RDG enable setting
5083INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5084{
5085 if (NULL == output_bool)
5086 return RETURN_ERR;
5087 *output_bool = TRUE;
5088 return RETURN_OK;
5089}
5090
5091//Set radio RDG enable setting
5092INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5093{
5094 return RETURN_ERR;
5095}
5096
5097//Get radio ADDBA enable setting
5098INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5099{
5100 if (NULL == output_bool)
5101 return RETURN_ERR;
5102 *output_bool = TRUE;
5103 return RETURN_OK;
5104}
5105
5106//Set radio ADDBA enable setting
5107INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5108{
5109 return RETURN_ERR;
5110}
5111
5112//Get radio auto block ack enable setting
5113INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5114{
5115 if (NULL == output_bool)
5116 return RETURN_ERR;
5117 *output_bool = TRUE;
5118 return RETURN_OK;
5119}
5120
5121//Set radio auto block ack enable setting
5122INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5123{
5124 return RETURN_ERR;
5125}
5126
5127//Get radio 11n pure mode enable support
5128INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5129{
5130 if (NULL == output_bool)
5131 return RETURN_ERR;
5132 *output_bool = TRUE;
5133 return RETURN_OK;
5134}
5135
5136//Get radio 11n pure mode enable setting
5137INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5138{
5139 if (NULL == output_bool)
5140 return RETURN_ERR;
5141 *output_bool = TRUE;
5142 return RETURN_OK;
5143}
5144
5145//Set radio 11n pure mode enable setting
5146INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5147{
5148 return RETURN_ERR;
5149}
5150
5151//Get radio IGMP snooping enable setting
5152INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5153{
developerd946fd62022-12-08 18:03:28 +08005154 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005155 char cmd[128]={0};
5156 char buf[4]={0};
5157 bool bridge = FALSE, mac80211 = FALSE;
5158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5159
5160 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005161 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005162
5163 *output_bool = FALSE;
5164
5165 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5166 _syscmd(cmd, buf, sizeof(buf));
5167 if (strncmp(buf, "1", 1) == 0)
5168 bridge = TRUE;
5169
developerac6f1142022-12-20 19:26:35 +08005170 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005171 return RETURN_ERR;
5172 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
developer81bf2ed2022-09-13 15:31:14 +08005173 _syscmd(cmd, buf, sizeof(buf));
5174 if (strncmp(buf, "1", 1) == 0)
5175 mac80211 = TRUE;
5176
5177 if (bridge && mac80211)
5178 *output_bool = TRUE;
5179
5180 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005181 return RETURN_OK;
5182}
5183
5184//Set radio IGMP snooping enable setting
5185INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5186{
developerd946fd62022-12-08 18:03:28 +08005187 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005188 char cmd[128]={0};
5189 char buf[4]={0};
developer894affa2023-05-10 18:13:19 +08005190 int max_num_radios = 0;
5191 int apIndex = 0;
developer81bf2ed2022-09-13 15:31:14 +08005192 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5193
5194 // bridge
developerfb09ba62023-06-09 17:03:21 +08005195 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
developer81bf2ed2022-09-13 15:31:14 +08005196 _syscmd(cmd, buf, sizeof(buf));
5197
developer804c64f2022-10-19 13:54:40 +08005198 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005199 // mac80211
developer894affa2023-05-10 18:13:19 +08005200 for (int i = 0; i < MAX_NUM_VAP_PER_RADIO; i++) {
5201 apIndex = radioIndex + i*max_num_radios;
5202 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5203 continue;
developerfb09ba62023-06-09 17:03:21 +08005204 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
developer81bf2ed2022-09-13 15:31:14 +08005205 _syscmd(cmd, buf, sizeof(buf));
5206 }
5207 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5208 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005209}
5210
5211//Get the Reset count of radio
5212INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5213{
5214 if (NULL == output_int)
5215 return RETURN_ERR;
5216 *output_int = (radioIndex==0)? 1: 3;
5217
5218 return RETURN_OK;
5219}
5220
5221
5222//---------------------------------------------------------------------------------------------------
5223//
5224// Additional Wifi AP level APIs used for Access Point devices
5225//
5226//---------------------------------------------------------------------------------------------------
5227
5228// creates a new ap and pushes these parameters to the hardware
5229INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5230{
developer7930d352022-12-21 17:55:42 +08005231 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005232 return RETURN_OK;
5233}
5234
5235// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5236INT wifi_deleteAp(INT apIndex)
5237{
developerd946fd62022-12-08 18:03:28 +08005238 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005239 char buf[128] = {0};
5240 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005241
developerac6f1142022-12-20 19:26:35 +08005242 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005243 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005244
developer89df4502023-02-16 20:45:02 +08005245 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5246 return RETURN_ERR;
5247
developer7930d352022-12-21 17:55:42 +08005248 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005249 _syscmd(cmd, buf, sizeof(buf));
5250
5251 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005252 return RETURN_OK;
5253}
5254
5255// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5256INT wifi_getApName(INT apIndex, CHAR *output_string)
5257{
developerd946fd62022-12-08 18:03:28 +08005258 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005259 if(NULL == output_string)
5260 return RETURN_ERR;
5261
developerac6f1142022-12-20 19:26:35 +08005262 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005263 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005264 else
5265 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005266 return RETURN_OK;
5267}
5268
5269// Outputs the index number in that corresponds to the SSID string
5270INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5271{
developerd946fd62022-12-08 18:03:28 +08005272 char cmd [128] = {0};
5273 char buf[32] = {0};
5274 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005275 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005276
developerefb790a2023-12-26 18:58:32 +08005277#ifdef DYNAMIC_IF_NAME
developerd946fd62022-12-08 18:03:28 +08005278 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5279 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005280
developerac6f1142022-12-20 19:26:35 +08005281 if (strlen(buf) != 0) {
5282 apIndex_str = strtok(buf, "\n");
5283 *output_int = strtoul(apIndex_str, NULL, 10);
5284 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005285 }
developerefb790a2023-12-26 18:58:32 +08005286#endif
developer67b8ee92022-12-20 10:48:43 +08005287 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5288 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5289 if (apIndex_str) {
5290 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5291 return RETURN_OK;
5292 }
developerd946fd62022-12-08 18:03:28 +08005293 *output_int = -1;
5294 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005295}
5296
5297INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5298{
5299 return wifi_getIndexFromName(inputSsidString, output_int);
5300}
5301
5302// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5303INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5304{
5305 char buf[MAX_BUF_SIZE] = {0};
5306 char cmd[MAX_CMD_SIZE] = {0};
5307 char config_file[MAX_BUF_SIZE] = {0};
5308
5309 if(NULL == output_string)
5310 return RETURN_ERR;
5311
5312 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005313 if (!syn_flag)
5314 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5315 else
developer07ded1f2024-01-10 10:30:15 +08005316 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08005317 if((strcmp(buf,"3")==0))
5318 snprintf(output_string, 32, "WPAand11i");
5319 else if((strcmp(buf,"2")==0))
5320 snprintf(output_string, 32, "11i");
5321 else if((strcmp(buf,"1")==0))
5322 snprintf(output_string, 32, "WPA");
5323 else
5324 snprintf(output_string, 32, "None");
5325
5326 return RETURN_OK;
5327}
5328
5329// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5330INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5331{
5332 char config_file[MAX_BUF_SIZE] = {0};
5333 struct params list;
5334
5335 if (NULL == beaconTypeString)
5336 return RETURN_ERR;
5337 list.name = "wpa";
5338 list.value = "0";
5339
5340 if((strcmp(beaconTypeString,"WPAand11i")==0))
5341 list.value="3";
5342 else if((strcmp(beaconTypeString,"11i")==0))
5343 list.value="2";
5344 else if((strcmp(beaconTypeString,"WPA")==0))
5345 list.value="1";
5346
5347 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5348 wifi_hostapdWrite(config_file, &list, 1);
5349 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developerefb790a2023-12-26 18:58:32 +08005350 snprintf(vap_info[apIndex].wpa, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08005351 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5352 return RETURN_OK;
5353}
5354
5355// sets the beacon interval on the hardware for this AP
5356INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5357{
developer5f222492022-09-13 15:21:52 +08005358 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5359 struct params params={'\0'};
5360 char buf[MAX_BUF_SIZE] = {'\0'};
5361 char config_file[MAX_BUF_SIZE] = {'\0'};
5362
5363 params.name = "beacon_int";
5364 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5365 params.value = buf;
5366
5367 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5368 wifi_hostapdWrite(config_file, &params, 1);
5369
5370 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5371 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5372 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005373}
5374
5375INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5376{
developer5b398df2022-11-17 20:39:48 +08005377 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5378 return RETURN_ERR;
5379 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005380}
5381
5382// Get the packet size threshold supported.
5383INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5384{
5385 //save config and apply instantly
5386 if (NULL == output_bool)
5387 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005388 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005389 return RETURN_OK;
5390}
5391
5392// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5393INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5394{
developer514406b2022-12-05 17:20:21 +08005395 char buf[16] = {0};
5396 char config_file[128] = {0};
5397 struct params param = {0};
5398
5399 if (threshold > 65535) {
5400 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5401 return RETURN_ERR;
5402 }
developer06a01d92022-09-07 16:32:39 +08005403
developer23e71282023-01-18 10:25:19 +08005404 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005405 snprintf(buf, sizeof(buf), "%u", threshold);
5406 param.name = "rts_threshold";
5407 param.value = buf;
5408 wifi_hostapdWrite(config_file, &param, 1);
5409 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5410 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005411
5412 return RETURN_OK;
5413}
5414
5415// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5416INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5417{
5418 if (NULL == output_string)
5419 return RETURN_ERR;
5420 snprintf(output_string, 32, "TKIPandAESEncryption");
5421 return RETURN_OK;
5422
5423}
5424
5425// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5426INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5427{
5428 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005429 char *param_name = NULL;
5430 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005431
5432 if(NULL == output_string)
5433 return RETURN_ERR;
5434
5435 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005436 if (!syn_flag)
5437 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5438 else
developer07ded1f2024-01-10 10:30:15 +08005439 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08005440
5441 if(strcmp(buf,"0")==0)
5442 {
5443 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5444 snprintf(output_string, 32, "None");
5445 return RETURN_OK;
5446 }
5447 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5448 param_name = "rsn_pairwise";
5449 else if((strcmp(buf,"1")==0))
5450 param_name = "wpa_pairwise";
5451 else
5452 return RETURN_ERR;
5453 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005454 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005455 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5456 param_name = "wpa_pairwise";
5457 memset(output_string, '\0', 32);
5458 wifi_hostapdRead(config_file, param_name, output_string, 32);
5459 }
developer06a01d92022-09-07 16:32:39 +08005460 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5461
developer72ec5572023-01-05 16:27:13 +08005462 if(strcmp(output_string,"TKIP CCMP") == 0)
5463 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5464 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005465 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5466 else if(strcmp(output_string,"CCMP") == 0)
5467 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005468
5469 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5470 return RETURN_OK;
5471}
5472
5473// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5474INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5475{
5476 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5477 struct params params={'\0'};
5478 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005479 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005480
5481 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005482 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005483
5484 if(strcmp(encMode, "TKIPEncryption") == 0)
5485 params.value = "TKIP";
5486 else if(strcmp(encMode,"AESEncryption") == 0)
5487 params.value = "CCMP";
5488 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5489 params.value = "TKIP CCMP";
5490
5491 if((strcmp(output_string,"WPAand11i")==0))
5492 {
5493 params.name = "wpa_pairwise";
5494 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5495 wifi_hostapdWrite(config_file, &params, 1);
5496 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5497
developer30423732022-12-01 16:17:49 +08005498 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005499 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5500 wifi_hostapdWrite(config_file, &params, 1);
5501 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5502
5503 return RETURN_OK;
5504 }
5505 else if((strcmp(output_string,"11i")==0))
5506 {
5507 params.name = "rsn_pairwise";
5508 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5509 wifi_hostapdWrite(config_file, &params, 1);
5510 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5511 return RETURN_OK;
5512 }
5513 else if((strcmp(output_string,"WPA")==0))
5514 {
5515 params.name = "wpa_pairwise";
5516 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5517 wifi_hostapdWrite(config_file, &params, 1);
5518 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5519 return RETURN_OK;
5520 }
5521
5522 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5523 return RETURN_OK;
5524}
5525
5526// deletes internal security varable settings for this ap
5527INT wifi_removeApSecVaribles(INT apIndex)
5528{
5529 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005530 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005531 //_syscmd(cmd, buf, sizeof(buf));
5532
developerd946fd62022-12-08 18:03:28 +08005533 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005534 //_syscmd(cmd, buf, sizeof(buf));
5535 return RETURN_ERR;
5536}
5537
5538// changes the hardware settings to disable encryption on this ap
5539INT wifi_disableApEncryption(INT apIndex)
5540{
5541 //Apply instantly
5542 return RETURN_ERR;
5543}
5544
5545// set the authorization mode on this ap
5546// mode mapping as: 1: open, 2: shared, 4:auto
5547INT wifi_setApAuthMode(INT apIndex, INT mode)
5548{
developeraf95c502022-09-13 16:18:22 +08005549 struct params params={0};
5550 char config_file[64] = {0};
5551 int ret;
5552
5553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5554
5555 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5556 params.name = "auth_algs";
5557
developer72ec5572023-01-05 16:27:13 +08005558 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005559 params.value = "3";
5560 else if (mode & 2)
5561 params.value = "2";
5562 else if (mode & 1)
5563 params.value = "1";
5564 else
5565 params.value = "0";
5566
5567 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5568 wifi_hostapdWrite(config_file, &params, 1);
5569 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005570 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5572
5573 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005574}
5575
5576// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5577INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5578{
5579 //save to wifi config, and wait for wifi restart to apply
5580 struct params params={'\0'};
5581 char config_file[MAX_BUF_SIZE] = {0};
5582 int ret;
5583
5584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5585 if(authMode == NULL)
5586 return RETURN_ERR;
5587
5588 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5589 params.name = "wpa_key_mgmt";
5590
5591 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5592 params.value = "WPA-PSK";
5593 else if(strcmp(authMode,"EAPAuthentication") == 0)
5594 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005595 else if (strcmp(authMode, "SAEAuthentication") == 0)
5596 params.value = "SAE";
5597 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5598 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005599 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5600 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005601 else if (strcmp(authMode, "Enhanced_Open") == 0)
5602 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005603 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5604 return RETURN_OK; //This is taken careof in beaconType
5605
5606 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5607 ret=wifi_hostapdWrite(config_file,&params,1);
5608 if(!ret)
5609 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
developerefb790a2023-12-26 18:58:32 +08005610 snprintf(vap_info[apIndex].wpa_key_mgmt, MAX_BUF_SIZE, "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08005611 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5612
5613 return ret;
5614}
5615
5616// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5617INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5618{
5619 //save to wifi config, and wait for wifi restart to apply
5620 char BeaconType[50] = {0};
5621 char config_file[MAX_BUF_SIZE] = {0};
5622
5623 *authMode = 0;
5624 wifi_getApBeaconType(apIndex,BeaconType);
5625 printf("%s____%s \n",__FUNCTION__,BeaconType);
5626
5627 if(strcmp(BeaconType,"None") == 0)
5628 strcpy(authMode,"None");
5629 else
5630 {
5631 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005632 if (!syn_flag)
5633 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5634 else
developer07ded1f2024-01-10 10:30:15 +08005635 snprintf(authMode, 32, "%s", vap_info[apIndex].wpa_key_mgmt);
developer06a01d92022-09-07 16:32:39 +08005636 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5637 if(strcmp(authMode,"WPA-PSK") == 0)
5638 strcpy(authMode,"SharedAuthentication");
5639 else if(strcmp(authMode,"WPA-EAP") == 0)
5640 strcpy(authMode,"EAPAuthentication");
5641 }
5642
5643 return RETURN_OK;
5644}
5645
5646// Outputs the number of stations associated per AP
5647INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5648{
developerd946fd62022-12-08 18:03:28 +08005649 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005650 char cmd[128]={0};
5651 char buf[128]={0};
5652 BOOL status = false;
5653
5654 if(apIndex > MAX_APS)
5655 return RETURN_ERR;
5656
5657 wifi_getApEnable(apIndex,&status);
5658 if (!status)
5659 return RETURN_OK;
5660
developerd946fd62022-12-08 18:03:28 +08005661 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005662 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005663 return RETURN_ERR;
5664 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005665 _syscmd(cmd, buf, sizeof(buf));
5666 sscanf(buf,"%lu", output_ulong);
5667
5668 return RETURN_OK;
5669}
5670
5671// manually removes any active wi-fi association with the device specified on this ap
5672INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5673{
developerd946fd62022-12-08 18:03:28 +08005674 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005675 char buf[126]={'\0'};
5676
developerac6f1142022-12-20 19:26:35 +08005677 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005678 return RETURN_ERR;
5679 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005680 system(buf);
5681
5682 return RETURN_OK;
5683}
5684
5685// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5686INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5687{
5688 if(NULL == output_int)
5689 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005690 int max_radio_num = 0;
5691 wifi_getMaxRadioNumber(&max_radio_num);
5692 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005693 return RETURN_OK;
5694}
5695
5696// sets the radio index for the specific ap
5697INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5698{
5699 //set to config only and wait for wifi reset to apply settings
5700 return RETURN_ERR;
5701}
5702
5703// Get the ACL MAC list per AP
5704INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5705{
developerd946fd62022-12-08 18:03:28 +08005706 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005707 char cmd[MAX_CMD_SIZE]={'\0'};
5708 int ret = 0;
5709
developerac6f1142022-12-20 19:26:35 +08005710 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005711 return RETURN_ERR;
5712 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005713 ret = _syscmd(cmd,macArray,buf_size);
5714 if (ret != 0)
5715 return RETURN_ERR;
5716
5717 return RETURN_OK;
5718}
5719
developere6aafda2022-09-13 14:59:28 +08005720INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5721{
developerd946fd62022-12-08 18:03:28 +08005722 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005723 char cmd[MAX_CMD_SIZE]={'\0'};
5724 int ret = 0;
5725
developerac6f1142022-12-20 19:26:35 +08005726 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005727 return RETURN_ERR;
5728 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005729 ret = _syscmd(cmd,macArray,buf_size);
5730 if (ret != 0)
5731 return RETURN_ERR;
5732
5733 return RETURN_OK;
5734}
5735
developer06a01d92022-09-07 16:32:39 +08005736// Get the list of stations associated per AP
5737INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5738{
developerd946fd62022-12-08 18:03:28 +08005739 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005740 char cmd[128];
5741
5742 if(apIndex > 3) //Currently supporting apIndex upto 3
5743 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005744 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005745 return RETURN_ERR;
5746 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5747 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005748 _syscmd(cmd, macArray, buf_size);
5749
5750 return RETURN_OK;
5751}
5752
developer2f995fb2023-02-24 10:40:44 +08005753INT getAddressControlMode(INT apIndex, INT *mode)
5754{
5755 char buf [16] = {0};
5756 char config_file[64] = {0};
5757
5758 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08005759 if (!syn_flag)
5760 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5761 else
developer07ded1f2024-01-10 10:30:15 +08005762 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer2f995fb2023-02-24 10:40:44 +08005763
5764 *mode = -1;
5765 // 0 use deny file, 1 use accept file
5766 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5767 *mode = (INT)strtol(buf, NULL, 10);
5768
5769 return RETURN_OK;
5770}
5771
developer06a01d92022-09-07 16:32:39 +08005772// adds the mac address to the filter list
5773//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5774INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5775{
5776 char cmd[MAX_CMD_SIZE]={'\0'};
5777 char buf[MAX_BUF_SIZE]={'\0'};
5778
developer2f995fb2023-02-24 10:40:44 +08005779 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005780 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005781
developer06a01d92022-09-07 16:32:39 +08005782 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5783 if(_syscmd(cmd,buf,sizeof(buf)))
5784 return RETURN_ERR;
5785
5786 return RETURN_OK;
5787}
5788
developer2f995fb2023-02-24 10:40:44 +08005789INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5790{
5791 char cmd[MAX_CMD_SIZE]={'\0'};
5792 char buf[MAX_BUF_SIZE]={'\0'};
5793
5794 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5795 return RETURN_ERR;
5796
5797 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5798 if(_syscmd(cmd,buf,sizeof(buf)))
5799 return RETURN_ERR;
5800
5801 return RETURN_OK;
5802}
5803
developer06a01d92022-09-07 16:32:39 +08005804// deletes the mac address from the filter list
5805//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5806INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5807{
5808 char cmd[MAX_CMD_SIZE]={'\0'};
5809 char buf[MAX_BUF_SIZE]={'\0'};
5810
5811#if 0
developerd946fd62022-12-08 18:03:28 +08005812 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005813 if(_syscmd(cmd,buf,sizeof(buf)))
5814 return RETURN_ERR;
5815
5816#endif
developer2f995fb2023-02-24 10:40:44 +08005817 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005818 if(_syscmd(cmd,buf,sizeof(buf)))
5819 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005820 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5821 if(_syscmd(cmd,buf,sizeof(buf)))
5822 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005823
5824 return RETURN_OK;
5825}
5826
5827// outputs the number of devices in the filter list
5828INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5829{
developere6aafda2022-09-13 14:59:28 +08005830 char cmd[MAX_BUF_SIZE]={0};
5831 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005832 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005833
5834 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5835 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005836 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005837
developer2f995fb2023-02-24 10:40:44 +08005838 getAddressControlMode(apIndex, &mode);
5839 if (mode == -1)
5840 return RETURN_OK;
5841
5842 if (mode == 0)
5843 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5844 else if (mode == 1)
5845 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005846 _syscmd(cmd, buf, sizeof(buf));
5847
developer2f995fb2023-02-24 10:40:44 +08005848 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005849
5850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5851 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005852}
5853
5854INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5855{
5856 char cmd[128]={'\0'};
5857 char buf[128]={'\0'};
5858
5859 if(strcmp(action,"DENY")==0)
5860 {
5861 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5862 system(buf);
5863 return RETURN_OK;
5864 }
5865
5866 if(strcmp(action,"ALLOW")==0)
5867 {
5868 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5869 system(buf);
5870 return RETURN_OK;
5871 }
5872
5873 return RETURN_ERR;
5874
5875}
5876
5877// enable kick for devices on acl black list
5878INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5879{
5880 char aclArray[512] = {0}, *acl = NULL;
5881 char assocArray[512] = {0}, *asso = NULL;
5882
developere6aafda2022-09-13 14:59:28 +08005883 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005884 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5885
5886 // if there are no devices connected there is nothing to do
5887 if (strlen(assocArray) < 17)
5888 return RETURN_OK;
5889
5890 if (enable == TRUE)
5891 {
5892 //kick off the MAC which is in ACL array (deny list)
5893 acl = strtok(aclArray, "\r\n");
5894 while (acl != NULL) {
5895 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5896 wifi_kickApAssociatedDevice(apIndex, acl);
5897
5898 acl = strtok(NULL, "\r\n");
5899 }
developere6aafda2022-09-13 14:59:28 +08005900 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005901 }
5902 else
5903 {
developere6aafda2022-09-13 14:59:28 +08005904 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005905 }
5906
5907#if 0
5908 //TODO: need to revisit below implementation
5909 char aclArray[512]={0}, *acl=NULL;
5910 char assocArray[512]={0}, *asso=NULL;
5911 char buf[256]={'\0'};
5912 char action[10]={'\0'};
5913 FILE *fr=NULL;
5914 char interface[10]={'\0'};
5915 char config_file[MAX_BUF_SIZE] = {0};
5916
5917 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5918 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5919 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5920 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5921
5922 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5923 system(buf);
5924 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5925 system(buf);
5926 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5927 system(buf);
5928 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5929 system(buf);
5930 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5931 system(buf);
5932
5933 if ( enable == TRUE )
5934 {
5935 int device_count=0;
5936 strcpy(action,"DENY");
5937 //kick off the MAC which is in ACL array (deny list)
5938 acl = strtok (aclArray,",");
5939 while (acl != NULL) {
5940 if(strlen(acl)>=17)
5941 {
5942 apply_rules(apIndex, acl,action,interface);
5943 device_count++;
5944 //Register mac to be blocked ,in syscfg.db persistent storage
5945 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5946 system(buf);
5947 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5948 system(buf);
5949 system("syscfg commit");
5950
5951 wifi_kickApAssociatedDevice(apIndex, acl);
5952 }
5953 acl = strtok (NULL, ",");
5954 }
5955 }
5956 else
5957 {
5958 int device_count=0;
5959 char cmdmac[20]={'\0'};
5960 strcpy(action,"ALLOW");
5961 //kick off the MAC which is not in ACL array (allow list)
5962 acl = strtok (aclArray,",");
5963 while (acl != NULL) {
5964 if(strlen(acl)>=17)
5965 {
5966 apply_rules(apIndex, acl,action,interface);
5967 device_count++;
5968 //Register mac to be Allowed ,in syscfg.db persistent storage
5969 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5970 system(buf);
5971 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5972 system(buf);
5973 sprintf(cmdmac,"%s",acl);
5974 }
5975 acl = strtok (NULL, ",");
5976 }
5977 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5978 system(buf);
5979
5980 //Disconnect the mac which is not in ACL
5981 asso = strtok (assocArray,",");
5982 while (asso != NULL) {
5983 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5984 wifi_kickApAssociatedDevice(apIndex, asso);
5985 asso = strtok (NULL, ",");
5986 }
5987 }
5988#endif
5989 return RETURN_OK;
5990}
5991
5992INT wifi_setPreferPrivateConnection(BOOL enable)
5993{
developer06a01d92022-09-07 16:32:39 +08005994 return RETURN_OK;
5995}
5996
5997// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5998INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5999{
developerd946fd62022-12-08 18:03:28 +08006000 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006001 int items = 1;
6002 struct params list[2];
6003 char buf[MAX_BUF_SIZE] = {0};
6004 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08006005 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08006006
6007 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08006008
developer10adcc12022-09-13 14:39:17 +08006009 if (filterMode == 0) {
6010 sprintf(buf, "%d", 0);
6011 list[0].value = buf;
6012
developer2f995fb2023-02-24 10:40:44 +08006013 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08006014 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006015 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08006016 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
6017 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006018 memset(cmd,0,sizeof(cmd));
6019 // Delete deny_mac_file in hostapd configuration
6020 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08006021 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006022 }
6023 else if (filterMode == 1) {
6024 sprintf(buf, "%d", filterMode);
6025 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08006026 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
6027 list[1].name = "accept_mac_file";
6028 list[1].value = acl_file;
6029 items = 2;
developer10adcc12022-09-13 14:39:17 +08006030 } else if (filterMode == 2) {
6031 //TODO: deny_mac_file
6032 sprintf(buf, "%d", 0);
6033 list[0].value = buf;
6034 list[1].name = "deny_mac_file";
6035 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
6036 list[1].value = deny_file;
6037 items = 2;
6038 } else {
6039 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006040 }
developer10adcc12022-09-13 14:39:17 +08006041
developer06a01d92022-09-07 16:32:39 +08006042 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6043 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08006044 if (multiple_set == FALSE) {
6045 wifi_setApEnable(apIndex, FALSE);
6046 wifi_setApEnable(apIndex, TRUE);
6047 }
developerefb790a2023-12-26 18:58:32 +08006048 snprintf(vap_info[apIndex].macaddr_acl, MAX_BUF_SIZE, "%s", list[0].value);
developer06a01d92022-09-07 16:32:39 +08006049
6050 return RETURN_OK;
6051
6052#if 0
6053 if(apIndex==0 || apIndex==1)
6054 {
6055 //set the filtermode
6056 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
6057 system(buf);
6058 system("syscfg commit");
6059
6060 if(filterMode==0)
6061 {
6062 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6063 system(buf);
6064 return RETURN_OK;
6065 }
6066 }
6067 return RETURN_OK;
6068#endif
6069}
6070
6071// 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.
6072INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6073{
6074 return RETURN_ERR;
6075}
6076
6077// gets the vlan ID for this ap from an internal enviornment variable
6078INT wifi_getApVlanID(INT apIndex, INT *output_int)
6079{
developer30423732022-12-01 16:17:49 +08006080 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08006081 {
6082 *output_int=100;
6083 return RETURN_OK;
6084 }
6085
6086 return RETURN_ERR;
6087}
6088
6089// sets the vlan ID for this ap to an internal enviornment variable
6090INT wifi_setApVlanID(INT apIndex, INT vlanId)
6091{
6092 //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)
6093 return RETURN_ERR;
6094}
6095
6096// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6097INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6098{
6099 snprintf(bridgeName, 32, "brlan0");
6100 snprintf(IP, 32, "10.0.0.1");
6101 snprintf(subnet, 32, "255.255.255.0");
6102
6103 return RETURN_OK;
6104}
6105
6106//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6107INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6108{
6109 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6110 return RETURN_ERR;
6111}
6112
6113// reset the vlan configuration for this ap
6114INT wifi_resetApVlanCfg(INT apIndex)
6115{
developerf5fef612022-09-20 19:38:26 +08006116 char original_config_file[64] = {0};
6117 char current_config_file[64] = {0};
6118 char buf[64] = {0};
6119 char cmd[64] = {0};
6120 char vlan_file[64] = {0};
6121 char vlan_tagged_interface[16] = {0};
6122 char vlan_bridge[16] = {0};
6123 char vlan_naming[16] = {0};
6124 struct params list[4] = {0};
6125 wifi_band band;
6126
6127 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6128
6129 band = wifi_index_to_band(apIndex);
6130 if (band == band_2_4)
6131 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006132 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006133 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006134 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006135 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6136
6137 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6138
6139 if (strlen(vlan_file) == 0)
6140 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006141
developerf5fef612022-09-20 19:38:26 +08006142 // The file should exist or this vap would not work.
6143 if (access(vlan_file, F_OK) != 0) {
6144 sprintf(cmd, "touch %s", vlan_file);
6145 _syscmd(cmd, buf, sizeof(buf));
6146 }
6147 list[0].name = "vlan_file";
6148 list[0].value = vlan_file;
6149
6150 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6151 list[1].name = "vlan_tagged_interface";
6152 list[1].value = vlan_tagged_interface;
6153
6154 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6155 list[2].name = "vlan_bridge";
6156 list[2].value = vlan_bridge;
6157
6158 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6159 list[3].name = "vlan_naming";
6160 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006161
developerf5fef612022-09-20 19:38:26 +08006162 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6163 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006164 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006165 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006166
developerf5fef612022-09-20 19:38:26 +08006167 // restart this ap
6168 wifi_setApEnable(apIndex, FALSE);
6169 wifi_setApEnable(apIndex, TRUE);
6170
6171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6172
6173 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006174}
6175
6176// 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.
6177INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6178{
6179 return RETURN_ERR;
6180}
6181
6182// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6183INT wifi_startHostApd()
6184{
6185 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6186 system("systemctl start hostapd.service");
6187 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6188 return RETURN_OK;
6189 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6190}
6191
6192// stops hostapd
6193INT wifi_stopHostApd()
6194{
6195 char cmd[128] = {0};
6196 char buf[128] = {0};
6197
6198 sprintf(cmd,"systemctl stop hostapd");
6199 _syscmd(cmd, buf, sizeof(buf));
6200
6201 return RETURN_OK;
6202}
6203
6204// restart hostapd dummy function
6205INT wifi_restartHostApd()
6206{
6207 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6208 system("systemctl restart hostapd-global");
6209 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6210
6211 return RETURN_OK;
6212}
6213
6214static int align_hostapd_config(int index)
6215{
6216 ULONG lval;
6217 wifi_getRadioChannel(index%2, &lval);
6218 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006219 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006220}
6221
6222// sets the AP enable status variable for the specified ap.
6223INT wifi_setApEnable(INT apIndex, BOOL enable)
6224{
developerd946fd62022-12-08 18:03:28 +08006225 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006226 char config_file[MAX_BUF_SIZE] = {0};
6227 char cmd[MAX_CMD_SIZE] = {0};
6228 char buf[MAX_BUF_SIZE] = {0};
6229 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006230 int max_radio_num = 0;
6231 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006232
6233 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006234
6235 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006236 if (enable == status)
6237 return RETURN_OK;
6238
developerac6f1142022-12-20 19:26:35 +08006239 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006240 return RETURN_ERR;
6241
developer06a01d92022-09-07 16:32:39 +08006242 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006243 int radioIndex = apIndex % max_radio_num;
6244 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006245 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6246 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006247 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006248 _syscmd(cmd, buf, sizeof(buf));
developer2f18b9f2023-03-17 19:32:57 +08006249 if (!(apIndex/max_radio_num)) {
6250 sprintf(cmd, "iw %s del", interface_name);
6251 _syscmd(cmd, buf, sizeof(buf));
6252 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6253 _syscmd(cmd, buf, sizeof(buf));
6254 }
developer439baa32024-05-02 15:54:58 +08006255 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", single_wiphy ? radioIndex : phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006256 _syscmd(cmd, buf, sizeof(buf));
6257 }
6258 else {
developerd946fd62022-12-08 18:03:28 +08006259 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006260 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006261 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006262 _syscmd(cmd, buf, sizeof(buf));
6263 }
developera77d84b2023-02-22 16:10:50 +08006264
developer431128d2022-12-16 15:30:41 +08006265 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006266 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006267 _syscmd(cmd, buf, sizeof(buf));
6268 //Wait for wifi up/down to apply
6269 return RETURN_OK;
6270}
6271
6272// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6273INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6274{
developerd946fd62022-12-08 18:03:28 +08006275 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006276 char cmd[MAX_CMD_SIZE] = {'\0'};
6277 char buf[MAX_BUF_SIZE] = {'\0'};
6278
6279 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6280 return RETURN_ERR;
6281
6282 *output_bool = 0;
6283
6284 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6285 {
developerac6f1142022-12-20 19:26:35 +08006286 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006287 *output_bool = FALSE;
6288 return RETURN_OK;
6289 }
6290 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006291 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6292 }
6293
6294 return RETURN_OK;
6295}
6296
6297// Outputs the AP "Enabled" "Disabled" status from driver
6298INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6299{
6300 char cmd[128] = {0};
6301 char buf[128] = {0};
6302 BOOL output_bool;
6303
6304 if ( NULL == output_string)
6305 return RETURN_ERR;
6306 wifi_getApEnable(apIndex,&output_bool);
6307
6308 if(output_bool == 1)
6309 snprintf(output_string, 32, "Up");
6310 else
6311 snprintf(output_string, 32, "Disable");
6312
6313 return RETURN_OK;
6314}
6315
6316//Indicates whether or not beacons include the SSID name.
6317// outputs a 1 if SSID on the AP is enabled, else outputs 0
6318INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6319{
6320 //get the running status
6321 char config_file[MAX_BUF_SIZE] = {0};
6322 char buf[16] = {0};
6323
6324 if (!output)
6325 return RETURN_ERR;
6326
6327 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006328 if (!syn_flag)
6329 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6330 else
developer07ded1f2024-01-10 10:30:15 +08006331 snprintf(buf, sizeof(buf), "%s",vap_info[apIndex].ignore_broadcast_ssid);
developer1d57d002022-10-12 18:03:15 +08006332 // default is enable
6333 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6334 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006335
6336 return RETURN_OK;
6337}
6338
6339// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6340INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6341{
6342 //store the config, apply instantly
6343 char config_file[MAX_BUF_SIZE] = {0};
6344 struct params list;
6345
6346 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6347 list.name = "ignore_broadcast_ssid";
6348 list.value = enable?"0":"1";
6349
6350 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6351 wifi_hostapdWrite(config_file, &list, 1);
6352 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6353 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006354 wifi_reloadAp(apIndex);
developerefb790a2023-12-26 18:58:32 +08006355 snprintf(vap_info[apIndex].ignore_broadcast_ssid, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08006356 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6357
6358 return RETURN_OK;
6359}
6360
6361//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6362INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6363{
6364 //get the running status
6365 if(!output_uint)
6366 return RETURN_ERR;
6367 *output_uint=16;
6368 return RETURN_OK;
6369}
6370
6371INT wifi_setApRetryLimit(INT apIndex, UINT number)
6372{
6373 //apply instantly
6374 return RETURN_ERR;
6375}
6376
6377//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6378INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6379{
6380 if(!output)
6381 return RETURN_ERR;
6382 *output=TRUE;
6383 return RETURN_OK;
6384}
6385
6386//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6387INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6388{
6389 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006390 char cmd[128] = {0};
6391 char buf[128] = {0};
6392 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006393 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006394
developer0b246d12022-09-30 15:24:20 +08006395 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006396
developer0b246d12022-09-30 15:24:20 +08006397 wifi_getMaxRadioNumber(&max_radio_num);
6398 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006399 phyId = radio_index_to_phy(radioIndex);
6400 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006401 _syscmd(cmd,buf, sizeof(buf));
6402
6403 if (strlen(buf) > 0)
6404 *output = true;
6405
6406 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006407
developer06a01d92022-09-07 16:32:39 +08006408 return RETURN_OK;
6409}
6410
6411//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6412INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6413{
6414 //get the running status from driver
6415 if(!output)
6416 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006417
6418 char config_file[MAX_BUF_SIZE] = {0};
6419 char buf[16] = {0};
6420
6421 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6422 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006423 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006424 *output = TRUE;
6425 else
6426 *output = FALSE;
6427
developer06a01d92022-09-07 16:32:39 +08006428 return RETURN_OK;
6429}
6430
6431// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6432INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6433{
6434 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006435 char config_file[MAX_BUF_SIZE] = {0};
6436 struct params list;
6437
6438 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6439 list.name = "wmm_enabled";
6440 list.value = enable?"1":"0";
6441
6442 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6443 wifi_hostapdWrite(config_file, &list, 1);
6444 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6445 wifi_reloadAp(apIndex);
6446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6447
6448 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006449}
6450
6451//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.
6452INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6453{
6454 //get the running status from driver
6455 if(!output)
6456 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006457
6458 char config_file[128] = {0};
6459 char buf[16] = {0};
6460
6461 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6462 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6463 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6464 *output = TRUE;
6465 else
6466 *output = FALSE;
6467
developer06a01d92022-09-07 16:32:39 +08006468 return RETURN_OK;
6469}
6470
6471// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6472INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6473{
6474 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006475 char config_file[MAX_BUF_SIZE] = {0};
6476 struct params list;
6477
6478 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6479 list.name = "uapsd_advertisement_enabled";
6480 list.value = enable?"1":"0";
6481
6482 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6483 wifi_hostapdWrite(config_file, &list, 1);
6484 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6485 wifi_reloadAp(apIndex);
6486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6487
6488 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006489}
6490
developer6daeb3f2022-09-30 13:36:39 +08006491// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006492INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6493{
developerd946fd62022-12-08 18:03:28 +08006494 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006495 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6496 char cmd[128] = {0};
6497 char buf[128] = {0};
6498 char ack_filepath[128] = {0};
6499 uint16_t bitmap = 0;
6500 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6501 FILE *f = NULL;
6502
6503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6504
6505 // Get current setting
6506 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6507 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6508 _syscmd(cmd, buf, sizeof(buf));
6509 if (strlen(buf) > 0)
6510 bitmap = strtoul(buf, NULL, 10);
6511
6512 bitmap = strtoul(buf, NULL, 10);
6513
6514 if (ackPolicy == TRUE) { // True, unset this class
6515 bitmap &= ~class_map[class];
6516 } else { // False, set this class
6517 bitmap |= class_map[class];
6518 }
6519
6520 f = fopen(ack_filepath, "w");
6521 if (f == NULL) {
6522 fprintf(stderr, "%s: fopen failed\n", __func__);
6523 return RETURN_ERR;
6524 }
6525 fprintf(f, "%hu", bitmap);
6526 fclose(f);
6527
developerac6f1142022-12-20 19:26:35 +08006528 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006529 return RETURN_ERR;
6530 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006531 _syscmd(cmd, buf, sizeof(buf));
6532
6533 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6534 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006535}
6536
6537//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.
6538INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6539{
6540 //get the running status from driver
6541 if(!output_uint)
6542 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006543
6544 char output[16]={'\0'};
6545 char config_file[MAX_BUF_SIZE] = {0};
6546
6547 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006548 if (!syn_flag)
6549 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6550 else
developer07ded1f2024-01-10 10:30:15 +08006551 snprintf(output, sizeof(output), "%s", vap_info[apIndex].max_sta);
developer0947e1a2022-09-13 14:15:25 +08006552 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6553 else {
6554 int device_num = atoi(output);
6555 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6556 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6557 return RETURN_ERR;
6558 }
6559 else {
6560 *output_uint = device_num;
6561 }
6562 }
6563
developer06a01d92022-09-07 16:32:39 +08006564 return RETURN_OK;
6565}
6566
6567INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6568{
6569 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006570 char str[MAX_BUF_SIZE]={'\0'};
6571 char cmd[MAX_CMD_SIZE]={'\0'};
6572 struct params params;
6573 char config_file[MAX_BUF_SIZE] = {0};
6574
6575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006576 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006577 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006578 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006579 }
6580 sprintf(str, "%d", number);
6581 params.name = "max_num_sta";
6582 params.value = str;
6583
6584 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6585 int ret = wifi_hostapdWrite(config_file, &params, 1);
6586 if (ret) {
6587 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6588 ,__func__, ret);
6589 }
6590
6591 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6592 if (ret) {
6593 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6594 ,__func__, ret);
6595 }
6596 wifi_reloadAp(apIndex);
6597 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6598
6599 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006600}
6601
6602//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.
6603INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6604{
6605 //get the current threshold
6606 if(!output_uint)
6607 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006608 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6609 if (*output_uint == 0)
6610 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006611 return RETURN_OK;
6612}
6613
6614INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6615{
6616 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006617 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6618 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006619 return RETURN_ERR;
6620}
6621
6622//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.
6623INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6624{
6625 if(!output_uint)
6626 return RETURN_ERR;
6627 *output_uint = 3;
6628 return RETURN_OK;
6629}
6630
6631//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6632INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6633{
6634 if(!output_uint)
6635 return RETURN_ERR;
6636 *output_uint = 3;
6637 return RETURN_OK;
6638}
6639
6640//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.
6641INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6642{
6643 if(!output_in_seconds)
6644 return RETURN_ERR;
6645 *output_in_seconds = 0;
6646 return RETURN_OK;
6647}
6648
6649//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
6650INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6651{
6652 if(!output || apIndex>=MAX_APS)
6653 return RETURN_ERR;
6654 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006655 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006656 return RETURN_OK;
6657}
6658
6659//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6660INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6661{
developer587c1b62022-09-27 15:58:59 +08006662 char config_file[128] = {0};
6663 char wpa[16] = {0};
6664 char key_mgmt[64] = {0};
6665 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006666 if (!output)
6667 return RETURN_ERR;
6668
6669 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006670 if (!syn_flag)
6671 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6672 else
developer07ded1f2024-01-10 10:30:15 +08006673 snprintf(wpa, sizeof(wpa), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006674
developer587c1b62022-09-27 15:58:59 +08006675 strcpy(output, "None");//Copying "None" to output string for default case
developerefb790a2023-12-26 18:58:32 +08006676 if (!syn_flag)
6677 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6678 else
developer07ded1f2024-01-10 10:30:15 +08006679 snprintf(key_mgmt, sizeof(key_mgmt), "%s", vap_info[apIndex].wpa_key_mgmt);
developer4a359672022-10-13 15:30:46 +08006680 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006681 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006682 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006683 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006684 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006685 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006686 snprintf(output, 32, "WPA-WPA2-Personal");
6687
developer72ec5572023-01-05 16:27:13 +08006688 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6689 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006690 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006691 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006692 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006693 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006694 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006695 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006696 snprintf(output, 32, "WPA-WPA2-Enterprise");
6697 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006698 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006699 snprintf(output, 32, "WPA3-Personal");
6700 else
developer4a359672022-10-13 15:30:46 +08006701 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006702 }
developer06a01d92022-09-07 16:32:39 +08006703
6704 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6705 return RETURN_OK;
6706#if 0
6707 //TODO: need to revisit below implementation
6708 char securityType[32], authMode[32];
6709 int enterpriseMode=0;
6710
6711 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6712 if(!output)
6713 return RETURN_ERR;
6714
6715 wifi_getApBeaconType(apIndex, securityType);
6716 strcpy(output,"None");//By default, copying "None" to output string
6717 if (strncmp(securityType,"None", strlen("None")) == 0)
6718 return RETURN_OK;
6719
6720 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6721 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6722
6723 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6724 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6725 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6726 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6727 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6728 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6729 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6730
6731 return RETURN_OK;
6732#endif
6733}
6734
6735INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6736{
6737 char securityType[32];
6738 char authMode[32];
6739
6740 //store settings and wait for wifi up to apply
6741 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6742 if(!encMode)
6743 return RETURN_ERR;
6744
developer06a01d92022-09-07 16:32:39 +08006745 if (strcmp(encMode, "None")==0)
6746 {
6747 strcpy(securityType,"None");
6748 strcpy(authMode,"None");
6749 }
6750 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6751 {
6752 strcpy(securityType,"WPAand11i");
6753 strcpy(authMode,"PSKAuthentication");
6754 }
6755 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6756 {
6757 strcpy(securityType,"WPAand11i");
6758 strcpy(authMode,"EAPAuthentication");
6759 }
6760 else if (strcmp(encMode, "WPA-Personal")==0)
6761 {
6762 strcpy(securityType,"WPA");
6763 strcpy(authMode,"PSKAuthentication");
6764 }
6765 else if (strcmp(encMode, "WPA-Enterprise")==0)
6766 {
6767 strcpy(securityType,"WPA");
6768 strcpy(authMode,"EAPAuthentication");
6769 }
6770 else if (strcmp(encMode, "WPA2-Personal")==0)
6771 {
6772 strcpy(securityType,"11i");
6773 strcpy(authMode,"PSKAuthentication");
6774 }
6775 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6776 {
6777 strcpy(securityType,"11i");
6778 strcpy(authMode,"EAPAuthentication");
6779 }
developer587c1b62022-09-27 15:58:59 +08006780 else if (strcmp(encMode, "WPA3-Personal") == 0)
6781 {
6782 strcpy(securityType,"11i");
6783 strcpy(authMode,"SAEAuthentication");
6784 }
developer4a359672022-10-13 15:30:46 +08006785 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006786 {
6787 strcpy(securityType, "11i");
6788 strcpy(authMode, "PSK-SAEAuthentication");
6789 }
developer587c1b62022-09-27 15:58:59 +08006790 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6791 {
6792 strcpy(securityType,"11i");
6793 strcpy(authMode,"EAP_192-bit_Authentication");
6794 }
developer5c9fee82023-01-13 14:44:16 +08006795 else if (strcmp(encMode, "OWE") == 0)
6796 {
6797 strcpy(securityType,"11i");
6798 strcpy(authMode,"Enhanced_Open");
6799 }
developer06a01d92022-09-07 16:32:39 +08006800 else
6801 {
6802 strcpy(securityType,"None");
6803 strcpy(authMode,"None");
6804 }
6805 wifi_setApBeaconType(apIndex, securityType);
6806 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6807 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6808
6809 return RETURN_OK;
6810}
6811
6812
developer4b102122023-02-15 10:53:03 +08006813// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006814//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006815INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6816{
developer30423732022-12-01 16:17:49 +08006817 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006818 char config_file[MAX_BUF_SIZE] = {0};
6819
6820 if(output_string==NULL)
6821 return RETURN_ERR;
6822
6823 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006824 if (!syn_flag)
6825 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6826 else
developer07ded1f2024-01-10 10:30:15 +08006827 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006828 if(strcmp(buf,"0")==0)
6829 {
6830 printf("wpa_mode is %s ......... \n",buf);
6831 return RETURN_ERR;
6832 }
6833
6834 wifi_dbg_printf("\nFunc=%s\n",__func__);
6835 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006836 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006837 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6838
6839 return RETURN_OK;
6840}
6841
developer4b102122023-02-15 10:53:03 +08006842// Set PreSharedKey associated with a Access Point.
6843// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006844INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6845{
6846 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6847 struct params params={'\0'};
6848 int ret;
6849 char config_file[MAX_BUF_SIZE] = {0};
6850
6851 if(NULL == preSharedKey)
6852 return RETURN_ERR;
6853
developer4b102122023-02-15 10:53:03 +08006854 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006855
developer4b102122023-02-15 10:53:03 +08006856 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006857 {
developer4b102122023-02-15 10:53:03 +08006858 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006859 return RETURN_ERR;
6860 }
6861 params.value = preSharedKey;
6862 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6863 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006864 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006865 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006866 wifi_reloadAp(apIndex);
6867 }
developer06a01d92022-09-07 16:32:39 +08006868 return ret;
6869 //TODO: call hostapd_cli for dynamic_config_control
6870}
6871
6872//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6873// outputs the passphrase, maximum 63 characters
6874INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6875{
6876 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6877
6878 wifi_dbg_printf("\nFunc=%s\n",__func__);
6879 if (NULL == output_string)
6880 return RETURN_ERR;
6881
6882 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006883 if (!syn_flag)
6884 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6885 else
developer07ded1f2024-01-10 10:30:15 +08006886 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006887 if(strcmp(buf,"0")==0)
6888 {
6889 printf("wpa_mode is %s ......... \n",buf);
6890 return RETURN_ERR;
6891 }
6892
developerefb790a2023-12-26 18:58:32 +08006893 if (!syn_flag)
6894 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6895 else
developer07ded1f2024-01-10 10:30:15 +08006896 snprintf(output_string, 64, "%s", vap_info[apIndex].wpa_passphrase);
developer06a01d92022-09-07 16:32:39 +08006897 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6898
6899 return RETURN_OK;
6900}
6901
6902// sets the passphrase enviornment variable, max 63 characters
6903INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6904{
6905 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6906 struct params params={'\0'};
6907 char config_file[MAX_BUF_SIZE] = {0};
6908 int ret;
6909
6910 if(NULL == passPhrase)
6911 return RETURN_ERR;
6912
6913 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6914 {
6915 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6916 return RETURN_ERR;
6917 }
6918 params.name = "wpa_passphrase";
6919 params.value = passPhrase;
6920 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6921 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006922 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006923 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006924 wifi_reloadAp(apIndex);
6925 }
developerefb790a2023-12-26 18:58:32 +08006926 snprintf(vap_info[apIndex].wpa_passphrase, MAX_BUF_SIZE, "%s", passPhrase);
developer06a01d92022-09-07 16:32:39 +08006927
6928 return ret;
6929}
6930
6931//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.
6932INT wifi_setApSecurityReset(INT apIndex)
6933{
developer8d583982022-09-20 11:28:22 +08006934 char original_config_file[64] = {0};
6935 char current_config_file[64] = {0};
6936 char buf[64] = {0};
6937 char cmd[64] = {0};
6938 char wpa[4] = {0};
6939 char wpa_psk[64] = {0};
6940 char wpa_passphrase[64] = {0};
6941 char wpa_psk_file[128] = {0};
6942 char wpa_key_mgmt[64] = {0};
6943 char wpa_pairwise[32] = {0};
6944 wifi_band band;
6945 struct params list[6];
6946
6947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6948
6949 band = wifi_index_to_band(apIndex);
6950 if (band == band_2_4)
6951 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006952 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006953 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006954 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006955 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6956 else
6957 return RETURN_ERR;
6958
6959 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6960 list[0].name = "wpa";
6961 list[0].value = wpa;
6962
6963 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6964 list[1].name = "wpa_psk";
6965 list[1].value = wpa_psk;
6966
6967 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6968 list[2].name = "wpa_passphrase";
6969 list[2].value = wpa_passphrase;
6970
6971 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6972
6973 if (strlen(wpa_psk_file) == 0)
6974 strcpy(wpa_psk_file, PSK_FILE);
6975
6976 if (access(wpa_psk_file, F_OK) != 0) {
6977 sprintf(cmd, "touch %s", wpa_psk_file);
6978 _syscmd(cmd, buf, sizeof(buf));
6979 }
6980 list[3].name = "wpa_psk_file";
6981 list[3].value = wpa_psk_file;
6982
6983 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6984 list[4].name = "wpa_key_mgmt";
6985 list[4].value = wpa_key_mgmt;
6986
6987 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6988 list[5].name = "wpa_pairwise";
6989 list[5].value = wpa_pairwise;
6990
6991 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6992 wifi_hostapdWrite(current_config_file, list, 6);
6993
6994 wifi_setApEnable(apIndex, FALSE);
6995 wifi_setApEnable(apIndex, TRUE);
6996
6997 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6998 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006999}
7000
7001//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).
7002INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7003{
developer8f2ddd52022-09-13 15:39:24 +08007004 char config_file[64] = {0};
7005 char buf[64] = {0};
7006 char cmd[256] = {0};
7007
7008 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7009
developer06a01d92022-09-07 16:32:39 +08007010 if(!IP_output || !Port_output || !RadiusSecret_output)
7011 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08007012
developer8f2ddd52022-09-13 15:39:24 +08007013 // Read the first matched config
7014 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7015 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7016 _syscmd(cmd, buf, sizeof(buf));
7017 strncpy(IP_output, buf, 64);
7018
7019 memset(buf, 0, sizeof(buf));
7020 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7021 _syscmd(cmd, buf, sizeof(buf));
7022 *Port_output = atoi(buf);
7023
7024 memset(buf, 0, sizeof(buf));
7025 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7026 _syscmd(cmd, buf, sizeof(buf));
7027 strncpy(RadiusSecret_output, buf, 64);
7028
7029 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007030 return RETURN_OK;
7031}
7032
7033INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7034{
developer8f2ddd52022-09-13 15:39:24 +08007035 char config_file[64] = {0};
7036 char port_str[8] = {0};
7037 char cmd[256] = {0};
7038 char buf[128] = {0};
7039
7040 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007041 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7042 return RETURN_ERR;
7043
7044 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7045 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007046
7047 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7048
7049 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7050 _syscmd(cmd, buf, sizeof(buf));
7051 memset(cmd, 0, sizeof(cmd));
7052
7053 snprintf(port_str, sizeof(port_str), "%d", port);
7054 if (strlen(buf) == 0)
7055 // Append
7056 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7057 "auth_server_addr=%s\\n"
7058 "auth_server_port=%s\\n"
7059 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7060 else {
7061 // Delete the three lines setting after the "# radius 1" comment
7062 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7063 _syscmd(cmd, buf, sizeof(buf));
7064 memset(cmd, 0, sizeof(cmd));
7065 // Use "# radius 1" comment to find the location to insert the radius setting
7066 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7067 "# radius 1\\n"
7068 "auth_server_addr=%s\\n"
7069 "auth_server_port=%s\\n"
7070 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7071 }
7072 if(_syscmd(cmd, buf, sizeof(buf))) {
7073 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7074 return RETURN_ERR;
7075 }
7076
7077 wifi_reloadAp(apIndex);
7078 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7079 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007080}
7081
7082INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7083{
developer8f2ddd52022-09-13 15:39:24 +08007084 char config_file[64] = {0};
7085 char buf[64] = {0};
7086 char cmd[256] = {0};
7087
7088 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7089
developer06a01d92022-09-07 16:32:39 +08007090 if(!IP_output || !Port_output || !RadiusSecret_output)
7091 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007092
7093 // Read the second matched config
7094 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7095 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7096 _syscmd(cmd, buf, sizeof(buf));
7097 strncpy(IP_output, buf, 64);
7098
7099 memset(buf, 0, sizeof(buf));
7100 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7101 _syscmd(cmd, buf, sizeof(buf));
7102 *Port_output = atoi(buf);
7103
7104 memset(buf, 0, sizeof(buf));
7105 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7106 _syscmd(cmd, buf, sizeof(buf));
7107 strncpy(RadiusSecret_output, buf, 64);
7108
7109 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007110 return RETURN_OK;
7111}
7112
7113INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7114{
developer8f2ddd52022-09-13 15:39:24 +08007115 char config_file[64] = {0};
7116 char port_str[8] = {0};
7117 char cmd[256] = {0};
7118 char buf[128] = {0};
7119
7120 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007121 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7122 return RETURN_ERR;
7123
7124 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7125 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007126
7127 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7128
7129 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7130 _syscmd(cmd, buf, sizeof(buf));
7131 memset(cmd, 0, sizeof(cmd));
7132
7133 snprintf(port_str, sizeof(port_str), "%d", port);
7134 if (strlen(buf) == 0)
7135 // Append
7136 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7137 "auth_server_addr=%s\\n"
7138 "auth_server_port=%s\\n"
7139 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7140 else {
7141 // Delete the three lines setting after the "# radius 2" comment
7142 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7143 _syscmd(cmd, buf, sizeof(buf));
7144 memset(cmd, 0, sizeof(cmd));
7145 // Use "# radius 2" comment to find the location to insert the radius setting
7146 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7147 "# radius 2\\n"
7148 "auth_server_addr=%s\\n"
7149 "auth_server_port=%s\\n"
7150 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7151 }
7152 if(_syscmd(cmd, buf, sizeof(buf))) {
7153 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7154 return RETURN_ERR;
7155 }
7156
7157 wifi_reloadAp(apIndex);
7158 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7159 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007160}
7161
7162//RadiusSettings
7163INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7164{
7165 if(!output)
7166 return RETURN_ERR;
7167
7168 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7169 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7170 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7171 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7172 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7173 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.
7174 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7175 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7176 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7177 //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.
7178
7179 return RETURN_OK;
7180}
7181
7182INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7183{
7184 //store the paramters, and apply instantly
7185 return RETURN_ERR;
7186}
7187
7188//Device.WiFi.AccessPoint.{i}.WPS.Enable
7189//Enables or disables WPS functionality for this access point.
7190// outputs the WPS enable state of this ap in output_bool
7191INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7192{
developerd946fd62022-12-08 18:03:28 +08007193 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007194 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer613892e2023-09-21 16:33:35 +08007195
7196 *output_bool=FALSE;
developer5b398df2022-11-17 20:39:48 +08007197 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007198 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007199 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer613892e2023-09-21 16:33:35 +08007200 return RETURN_OK;
developerd946fd62022-12-08 18:03:28 +08007201 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007202 _syscmd(cmd, buf, sizeof(buf));
7203 if(strstr(buf, "configured"))
7204 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08007205
7206 return RETURN_OK;
developer613892e2023-09-21 16:33:35 +08007207}
developer06a01d92022-09-07 16:32:39 +08007208
7209//Device.WiFi.AccessPoint.{i}.WPS.Enable
7210// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7211INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7212{
7213 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007214 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007215 struct params params;
7216
developer06a01d92022-09-07 16:32:39 +08007217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7218 //store the paramters, and wait for wifi up to apply
7219 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007220 if (enable == TRUE) {
7221 wifi_getApBeaconType(apIndex, buf);
7222 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7223 params.value = "1";
7224 else // If ap set encryption
7225 params.value = "2";
7226 } else {
7227 params.value = "0";
7228 }
developer06a01d92022-09-07 16:32:39 +08007229
7230 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7231 wifi_hostapdWrite(config_file, &params, 1);
7232 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7233 wifi_reloadAp(apIndex);
7234
7235 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7236 return RETURN_OK;
7237}
7238
7239//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
7240INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7241{
7242 if(!output)
7243 return RETURN_ERR;
7244 snprintf(output, 128, "PushButton,PIN");
7245 return RETURN_OK;
7246}
7247
7248//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7249//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.
7250// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7251INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7252{
7253 if(!output)
7254 return RETURN_ERR;
7255 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7256
7257 return RETURN_OK;
7258}
7259
7260//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7261// 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
7262INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7263{
7264 //apply instantly. No setting need to be stored.
7265 char methods[MAX_BUF_SIZE], *token, *next_token;
7266 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7267 struct params params;
7268
developer5b398df2022-11-17 20:39:48 +08007269 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007270 return RETURN_ERR;
7271 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7272 //store the paramters, and wait for wifi up to apply
7273
7274 snprintf(methods, sizeof(methods), "%s", methodString);
7275 for(token=methods; *token; token=next_token)
7276 {
7277 strtok_r(token, ",", &next_token);
7278 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7279 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7280 else if(*token=='E')
7281 {
7282 if(!strcmp(methods, "Ethernet"))
7283 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7284 else if(!strcmp(methods, "ExternalNFCToken"))
7285 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7286 else
7287 printf("%s: Unknown WpsConfigMethod\n", __func__);
7288 }
7289 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7290 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7291 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7292 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7293 else if(*token=='P' )
7294 {
7295 if(!strcmp(token, "PushButton"))
developer894affa2023-05-10 18:13:19 +08007296 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer06a01d92022-09-07 16:32:39 +08007297 else if(!strcmp(token, "PIN"))
7298 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7299 else
7300 printf("%s: Unknown WpsConfigMethod\n", __func__);
7301 }
7302 else
7303 printf("%s: Unknown WpsConfigMethod\n", __func__);
7304 }
7305 params.name = "config_methods";
7306 params.value = config_methods;
7307 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7308 wifi_hostapdWrite(config_file, &params, 1);
7309 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7310 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7311
7312 return RETURN_OK;
7313}
7314
7315// outputs the pin value, ulong_pin must be allocated by the caller
7316INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7317{
7318 char buf[MAX_BUF_SIZE] = {0};
7319 char cmd[MAX_CMD_SIZE] = {0};
7320
developer5b398df2022-11-17 20:39:48 +08007321 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007322 return RETURN_ERR;
7323 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7324 _syscmd(cmd, buf, sizeof(buf));
7325 if(strlen(buf) > 0)
7326 *output_ulong=strtoul(buf, NULL, 10);
7327
7328 return RETURN_OK;
7329}
7330
7331// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7332INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7333{
7334 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7335 char ap_pin[16] = {0};
7336 char buf[MAX_BUF_SIZE] = {0};
7337 char config_file[MAX_BUF_SIZE] = {0};
7338 ULONG prev_pin = 0;
7339 struct params params;
7340
developer06a01d92022-09-07 16:32:39 +08007341 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7342 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7343 params.name = "ap_pin";
7344 params.value = ap_pin;
7345 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7346 wifi_hostapdWrite(config_file, &params, 1);
7347 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7348 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7349
7350 return RETURN_OK;
7351}
7352
7353// Output string is either Not configured or Configured, max 32 characters
7354INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7355{
developerd946fd62022-12-08 18:03:28 +08007356 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007357 char cmd[MAX_CMD_SIZE];
7358 char buf[MAX_BUF_SIZE]={0};
7359
developer5b398df2022-11-17 20:39:48 +08007360 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007361 return RETURN_ERR;
7362 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7363 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007364 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007365 return RETURN_ERR;
7366 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007367 _syscmd(cmd, buf, sizeof(buf));
7368
developer348e3d92022-09-13 14:48:41 +08007369 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007370 snprintf(output_string, 32, "Configured");
7371 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7372
7373 return RETURN_OK;
7374}
7375
7376// sets the WPS pin for this AP
7377INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7378{
developerd946fd62022-12-08 18:03:28 +08007379 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007380 char cmd[MAX_CMD_SIZE];
7381 char buf[MAX_BUF_SIZE]={0};
7382 BOOL enable;
7383
developer06a01d92022-09-07 16:32:39 +08007384 wifi_getApEnable(apIndex, &enable);
7385 if (!enable)
7386 return RETURN_ERR;
7387 wifi_getApWpsEnable(apIndex, &enable);
7388 if (!enable)
7389 return RETURN_ERR;
7390
developerac6f1142022-12-20 19:26:35 +08007391 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007392 return RETURN_ERR;
7393 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007394 _syscmd(cmd, buf, sizeof(buf));
7395 if((strstr(buf, "OK"))!=NULL)
7396 return RETURN_OK;
7397
7398 return RETURN_ERR;
7399}
7400
7401// This function is called when the WPS push button has been pressed for this AP
7402INT wifi_setApWpsButtonPush(INT apIndex)
7403{
7404 char cmd[MAX_CMD_SIZE];
7405 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007406 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007407 BOOL enable=FALSE;
7408
developer06a01d92022-09-07 16:32:39 +08007409 wifi_getApEnable(apIndex, &enable);
7410 if (!enable)
7411 return RETURN_ERR;
7412
7413 wifi_getApWpsEnable(apIndex, &enable);
7414 if (!enable)
7415 return RETURN_ERR;
7416
developerac6f1142022-12-20 19:26:35 +08007417 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007418 return RETURN_ERR;
7419
developer900e2b72023-05-23 10:23:48 +08007420 snprintf(cmd, sizeof(cmd), "sleep 1 && hostapd_cli -i%s wps_cancel && hostapd_cli -i%s wps_pbc", interface_name, interface_name);
developer06a01d92022-09-07 16:32:39 +08007421 _syscmd(cmd, buf, sizeof(buf));
7422
7423 if((strstr(buf, "OK"))!=NULL)
7424 return RETURN_OK;
7425 return RETURN_ERR;
7426}
7427
7428// cancels WPS mode for this AP
7429INT wifi_cancelApWPS(INT apIndex)
7430{
developerd946fd62022-12-08 18:03:28 +08007431 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007432 char cmd[MAX_CMD_SIZE];
7433 char buf[MAX_BUF_SIZE]={0};
7434
developerac6f1142022-12-20 19:26:35 +08007435 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007436 return RETURN_ERR;
7437 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007438 _syscmd(cmd,buf, sizeof(buf));
7439
7440 if((strstr(buf, "OK"))!=NULL)
7441 return RETURN_OK;
7442 return RETURN_ERR;
7443}
7444
7445//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7446//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7447INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7448{
developerd946fd62022-12-08 18:03:28 +08007449 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007450 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007451 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007452 char cmd[256] = {0}, buf[2048] = {0};
7453 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007454 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007455 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007456 wifi_associated_dev_t *dev=NULL;
7457
7458 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7459 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007460 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007461 return RETURN_ERR;
7462 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007463 _syscmd(cmd,buf,sizeof(buf));
7464 *output_array_size = atoi(buf);
7465
7466 if (*output_array_size <= 0)
7467 return RETURN_OK;
7468
7469 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7470 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007471 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007472 _syscmd(cmd,buf,sizeof(buf));
7473 f = fopen("/tmp/connected_devices.txt", "r");
7474 if (f==NULL)
7475 {
7476 *output_array_size=0;
7477 return RETURN_ERR;
7478 }
developer30423732022-12-01 16:17:49 +08007479 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007480 {
7481 param = strtok(line,"=");
7482 value = strtok(NULL,"=");
7483
7484 if( strcmp("flags",param) == 0 )
7485 {
7486 value[strlen(value)-1]='\0';
7487 if(strstr (value,"AUTHORIZED") != NULL )
7488 {
7489 dev[auth_temp].cli_AuthenticationState = 1;
7490 dev[auth_temp].cli_Active = 1;
7491 auth_temp++;
7492 read_flag=1;
7493 }
7494 }
7495 if(read_flag==1)
7496 {
7497 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7498 {
7499 value[strlen(value)-1]='\0';
7500 sscanf(value, "%x:%x:%x:%x:%x:%x",
7501 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7502 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7503 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7504 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7505 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7506 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7507 mac_temp++;
7508 read_flag=0;
7509 }
7510 }
7511 }
7512 *output_array_size = auth_temp;
7513 auth_temp=0;
7514 mac_temp=0;
7515 free(line);
7516 fclose(f);
7517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7518 return RETURN_OK;
7519}
7520
7521#define MACADDRESS_SIZE 6
7522
7523INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7524{
7525 FILE *fp = NULL;
7526 char str[MAX_BUF_SIZE] = {0};
7527 int wificlientindex = 0 ;
7528 int count = 0;
7529 int signalstrength = 0;
7530 int arr[MACADDRESS_SIZE] = {0};
7531 unsigned char mac[MACADDRESS_SIZE] = {0};
7532 UINT wifi_count = 0;
7533 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7534 char pipeCmd[MAX_CMD_SIZE] = {0};
7535
7536 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7537 *output_array_size = 0;
7538 *associated_dev_array = NULL;
7539
7540 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7541 fp = popen(pipeCmd, "r");
7542 if (fp == NULL)
7543 {
7544 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7545 return RETURN_ERR;
7546 }
7547
7548 /* Read the output a line at a time - output it. */
7549 fgets(str, sizeof(str)-1, fp);
7550 wifi_count = (unsigned int) atoi ( str );
7551 *output_array_size = wifi_count;
7552 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7553 pclose(fp);
7554
7555 if(wifi_count == 0)
7556 {
7557 return RETURN_OK;
7558 }
7559 else
7560 {
7561 wifi_associated_dev3_t* temp = NULL;
7562 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7563 if(temp == NULL)
7564 {
7565 printf("Error Statement. Insufficient memory \n");
7566 return RETURN_ERR;
7567 }
7568
7569 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7570 system(pipeCmd);
7571 memset(pipeCmd,0,sizeof(pipeCmd));
7572 if(apIndex == 0)
7573 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7574 else if(apIndex == 1)
7575 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7576 system(pipeCmd);
7577
7578 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7579 if(fp == NULL)
7580 {
7581 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007582 free(temp);
developer06a01d92022-09-07 16:32:39 +08007583 return RETURN_ERR;
7584 }
7585 fclose(fp);
7586
developer30423732022-12-01 16:17:49 +08007587 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007588 fp = popen(pipeCmd, "r");
7589 if(fp)
7590 {
7591 for(count =0 ; count < wifi_count; count++)
7592 {
7593 fgets(str, MAX_BUF_SIZE, fp);
7594 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7595 {
7596 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7597 {
7598 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7599
7600 }
7601 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7602 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]);
7603 }
7604 temp[count].cli_AuthenticationState = 1; //TODO
7605 temp[count].cli_Active = 1; //TODO
7606 }
7607 pclose(fp);
7608 }
7609
developer30423732022-12-01 16:17:49 +08007610 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
developer06a01d92022-09-07 16:32:39 +08007611 fp = popen(pipeCmd, "r");
7612 if(fp)
7613 {
7614 pclose(fp);
7615 }
7616 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7617 if(fp)
7618 {
7619 for(count =0 ; count < wifi_count ;count++)
7620 {
7621 fgets(str, MAX_BUF_SIZE, fp);
7622 signalstrength = atoi(str);
7623 temp[count].cli_SignalStrength = signalstrength;
7624 temp[count].cli_RSSI = signalstrength;
7625 temp[count].cli_SNR = signalstrength + 95;
7626 }
7627 pclose(fp);
7628 }
7629
7630
7631 if((apIndex == 0) || (apIndex == 4))
7632 {
7633 for(count =0 ; count < wifi_count ;count++)
7634 {
7635 strcpy(temp[count].cli_OperatingStandard,"g");
7636 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7637 }
7638
7639 //BytesSent
developer30423732022-12-01 16:17:49 +08007640 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007641 fp = popen(pipeCmd, "r");
7642 if(fp)
7643 {
7644 pclose(fp);
7645 }
7646 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7647 if(fp)
7648 {
7649 for (count = 0; count < wifi_count; count++)
7650 {
7651 fgets(str, MAX_BUF_SIZE, fp);
7652 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7653 }
7654 pclose(fp);
7655 }
7656
7657 //BytesReceived
developer30423732022-12-01 16:17:49 +08007658 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007659 fp = popen(pipeCmd, "r");
7660 if (fp)
7661 {
7662 pclose(fp);
7663 }
7664 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7665 if (fp)
7666 {
7667 for (count = 0; count < wifi_count; count++)
7668 {
7669 fgets(str, MAX_BUF_SIZE, fp);
7670 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7671 }
7672 pclose(fp);
7673 }
7674
7675 //PacketsSent
developer30423732022-12-01 16:17:49 +08007676 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007677 fp = popen(pipeCmd, "r");
7678 if (fp)
7679 {
7680 pclose(fp);
7681 }
7682
7683 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7684 if (fp)
7685 {
7686 for (count = 0; count < wifi_count; count++)
7687 {
7688 fgets(str, MAX_BUF_SIZE, fp);
7689 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7690 }
7691 pclose(fp);
7692 }
7693
7694 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007695 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007696 fp = popen(pipeCmd, "r");
7697 if (fp)
7698 {
7699 pclose(fp);
7700 }
7701 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7702 if (fp)
7703 {
7704 for (count = 0; count < wifi_count; count++)
7705 {
7706 fgets(str, MAX_BUF_SIZE, fp);
7707 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7708 }
7709 pclose(fp);
7710 }
7711
7712 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007713 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
developer06a01d92022-09-07 16:32:39 +08007714 fp = popen(pipeCmd, "r");
7715 if (fp)
7716 {
7717 pclose(fp);
7718 }
7719 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7720 if (fp)
7721 {
7722 for (count = 0; count < wifi_count; count++)
7723 {
7724 fgets(str, MAX_BUF_SIZE, fp);
7725 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7726 }
7727 pclose(fp);
7728 }
7729
7730 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007731 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
developer06a01d92022-09-07 16:32:39 +08007732 fp = popen(pipeCmd, "r");
7733 if (fp)
7734 {
7735 pclose(fp);
7736 }
7737 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7738 if (fp)
7739 {
7740 for (count = 0; count < wifi_count; count++)
7741 {
7742 fgets(str, MAX_BUF_SIZE, fp);
7743 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7744 }
7745 pclose(fp);
7746 }
7747
7748 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007749 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007750 fp = popen(pipeCmd, "r");
7751 if (fp)
7752 {
7753 pclose(fp);
7754 }
7755 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7756 if (fp)
7757 {
7758 for (count = 0; count < wifi_count; count++)
7759 {
7760 fgets(str, MAX_BUF_SIZE, fp);
7761 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7762 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7763 }
7764 pclose(fp);
7765 }
7766
7767 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007768 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007769 fp = popen(pipeCmd, "r");
7770 if (fp)
7771 {
7772 pclose(fp);
7773 }
7774 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7775 if (fp)
7776 {
7777 for (count = 0; count < wifi_count; count++)
7778 {
7779 fgets(str, MAX_BUF_SIZE, fp);
7780 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7781 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7782 }
7783 pclose(fp);
7784 }
7785
7786 }
7787 else if ((apIndex == 1) || (apIndex == 5))
7788 {
7789 for (count = 0; count < wifi_count; count++)
7790 {
7791 strcpy(temp[count].cli_OperatingStandard, "a");
7792 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7793 temp[count].cli_BytesSent = 0;
7794 temp[count].cli_BytesReceived = 0;
7795 temp[count].cli_LastDataUplinkRate = 0;
7796 temp[count].cli_LastDataDownlinkRate = 0;
7797 temp[count].cli_PacketsSent = 0;
7798 temp[count].cli_PacketsReceived = 0;
7799 temp[count].cli_ErrorsSent = 0;
7800 }
7801 }
7802
7803 for (count = 0; count < wifi_count; count++)
7804 {
7805 temp[count].cli_Retransmissions = 0;
7806 temp[count].cli_DataFramesSentAck = 0;
7807 temp[count].cli_DataFramesSentNoAck = 0;
7808 temp[count].cli_MinRSSI = 0;
7809 temp[count].cli_MaxRSSI = 0;
7810 strncpy(temp[count].cli_InterferenceSources, "", 64);
7811 memset(temp[count].cli_IPAddress, 0, 64);
7812 temp[count].cli_RetransCount = 0;
7813 temp[count].cli_FailedRetransCount = 0;
7814 temp[count].cli_RetryCount = 0;
7815 temp[count].cli_MultipleRetryCount = 0;
7816 }
7817 *associated_dev_array = temp;
7818 }
7819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7820 return RETURN_OK;
7821}
7822
7823int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7824{
7825 FILE *fp = NULL;
7826 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7827 char cmd[MAX_CMD_SIZE];
7828 int count = 0;
7829
7830 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7831 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7832 fp = popen(cmd,"r");
7833 if(fp == NULL)
7834 {
7835 printf("Failed to run command in Function %s\n",__FUNCTION__);
7836 return 0;
7837 }
7838 if(fgets(path, sizeof(path)-1, fp) != NULL)
7839 {
7840 for(count=0;path[count]!='\n';count++)
7841 status[count]=path[count];
7842 status[count]='\0';
7843 }
7844 strcpy(wifi_status,status);
7845 pclose(fp);
7846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7847 return RETURN_OK;
7848}
7849
7850/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7851struct hostapd_sta_param {
7852 char key[50];
7853 char value[100];
7854}
7855
7856static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7857 int i = 0;
7858
7859 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7860 if (strncmp(params[i].key,key,50) == 0){
7861 return &params[i].value;
7862 }
7863 i++;
7864 }
7865 return NULL;
7866
7867} */
7868
7869static unsigned int count_occurences(const char *buf, const char *word)
7870{
7871 unsigned int n = 0;
7872 char *ptr = strstr(buf, word);
7873
7874 while (ptr++) {
7875 n++;
7876 ptr = strstr(ptr, word);
7877 }
7878
7879 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7880 return n;
7881}
7882
7883static const char *get_line_from_str_buf(const char *buf, char *line)
7884{
7885 int i;
7886 int n = strlen(buf);
7887
7888 for (i = 0; i < n; i++) {
7889 line[i] = buf[i];
7890 if (buf[i] == '\n') {
7891 line[i] = '\0';
7892 return &buf[i + 1];
7893 }
7894 }
7895
7896 return NULL;
7897}
7898
developer9a9f46e2023-11-09 09:22:42 +08007899static INT wifi_getAssocConnectMode(INT apIndex, CHAR *input_string, CHAR *OperatingStandard)
7900{
7901 wifi_band band;
7902 int ieee80211_mode = 0;
7903
7904 if (!input_string || !OperatingStandard)
7905 return RETURN_ERR;
7906
7907 band = wifi_index_to_band(apIndex);
7908
7909 if (strstr(input_string, "HE"))
7910 ieee80211_mode = WIFI_MODE_AX;
7911 else if (strstr(input_string, "VHT"))
7912 ieee80211_mode = WIFI_MODE_AC;
7913 else if (strstr(input_string, "EHT"))
7914 ieee80211_mode = WIFI_MODE_BE;
7915
7916 switch (ieee80211_mode) {
7917 case WIFI_MODE_AC:
7918 strncpy(OperatingStandard, "ac", 2);
7919 break;
7920 case WIFI_MODE_AX:
7921 strncpy(OperatingStandard, "ax", 2);
7922 break;
7923 case WIFI_MODE_BE:
7924 strncpy(OperatingStandard, "be", 2);
7925 break;
7926 default:
7927 if(band == band_2_4)
7928 strncpy(OperatingStandard,"b,g,n", 5);
7929 else if(band == band_5)
7930 strncpy(OperatingStandard,"a,n", 3);
7931 else if(band == band_6)
7932 strncpy(OperatingStandard,"ax", 2);
7933 else {
7934 wifi_dbg_printf("%s: failed to parse band %d\n", __FUNCTION__, band);
7935 return RETURN_ERR;
7936 }
7937 }
7938
7939
7940 return RETURN_OK;
7941}
7942
developer06a01d92022-09-07 16:32:39 +08007943INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7944{
7945 unsigned int assoc_cnt = 0;
7946 char interface_name[50] = {0};
7947 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7948 char cmd[MAX_CMD_SIZE] = {'\0'};
7949 char line[256] = {'\0'};
7950 int i = 0;
7951 int ret = 0;
7952 const char *ptr = NULL;
7953 char *key = NULL;
7954 char *val = NULL;
7955 wifi_associated_dev3_t *temp = NULL;
7956 int rssi;
7957
7958 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7959
7960 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7961 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7962 return RETURN_ERR;
7963 }
7964
7965 // Example filtered output of 'iw dev' command:
7966 // Station 0a:69:72:10:d2:fa (on wifi0)
7967 // signal avg:-67 [-71, -71] dBm
7968 // Station 28:c2:1f:25:5f:99 (on wifi0)
7969 // signal avg:-67 [-71, -70] dBm
developer9a9f46e2023-11-09 09:22:42 +08007970 if (sprintf(cmd,"iw dev %s station dump | tr -d '\t' | grep -E 'Station|signal avg"
7971 "|tx bitrate|rx bitrate'", interface_name) < 0) {
7972 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
developer06a01d92022-09-07 16:32:39 +08007973 return RETURN_ERR;
7974 }
7975
7976 ret = _syscmd(cmd, buf, sizeof(buf));
7977 if (ret == RETURN_ERR) {
7978 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7979 return RETURN_ERR;
7980 }
7981
7982 *output_array_size = count_occurences(buf, "Station");
7983 if (*output_array_size == 0) return RETURN_OK;
7984
7985 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7986 if (temp == NULL) {
7987 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7988 return RETURN_ERR;
7989 }
7990 *associated_dev_array = temp;
7991
7992 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7993 ptr = get_line_from_str_buf(buf, line);
7994 i = -1;
7995 while (ptr) {
7996 if (strstr(line, "Station")) {
7997 i++;
7998 key = strtok(line, " ");
7999 val = strtok(NULL, " ");
8000 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8001 &temp[i].cli_MACAddress[0],
8002 &temp[i].cli_MACAddress[1],
8003 &temp[i].cli_MACAddress[2],
8004 &temp[i].cli_MACAddress[3],
8005 &temp[i].cli_MACAddress[4],
8006 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8007 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8008 free(*associated_dev_array);
8009 return RETURN_ERR;
8010 }
8011 }
8012 else if (i < 0) {
developer9a9f46e2023-11-09 09:22:42 +08008013 wifi_dbg_printf("%s: not find station\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +08008014 ptr = get_line_from_str_buf(ptr, line);
8015 continue; // We didn't detect 'station' entry yet
8016 }
8017 else if (strstr(line, "signal avg")) {
8018 key = strtok(line, ":");
8019 val = strtok(NULL, " ");
8020 if (sscanf(val, "%d", &rssi) <= 0 ) {
8021 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8022 free(*associated_dev_array);
8023 return RETURN_ERR;
8024 }
8025 temp[i].cli_RSSI = rssi;
8026 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8027 }
developer9a9f46e2023-11-09 09:22:42 +08008028 else if (strstr(line, "tx bitrate")) {
8029 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8030 if (ret == RETURN_ERR) {
8031 wifi_dbg_printf("%s: failed to execute tx get assoc connect mode command.\n", __FUNCTION__);
8032 return ret;
8033 }
8034 }
8035 else if (strstr(line, "rx bitrate")) {
8036 /* if tx get ac, ax, be mode, need not get mode from rx */
8037 if (strncmp(temp[i].cli_OperatingStandard,"ac", 2) &&
8038 strncmp(temp[i].cli_OperatingStandard,"ax", 2) &&
8039 strncmp(temp[i].cli_OperatingStandard,"be", 2)) {
8040 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8041 if (ret == RETURN_ERR) {
8042 wifi_dbg_printf("%s: failed to execute rx get assoc connect mode command.\n", __FUNCTION__);
8043 return ret;
8044 }
8045 }
8046 }
developer06a01d92022-09-07 16:32:39 +08008047 // Here other fields can be parsed if added to filter of 'iw dev' command
developer06a01d92022-09-07 16:32:39 +08008048 ptr = get_line_from_str_buf(ptr, line);
developer9a9f46e2023-11-09 09:22:42 +08008049 }
developer06a01d92022-09-07 16:32:39 +08008050
8051 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008052 return RETURN_OK;
8053}
8054
8055#if 0
8056//To-do
8057INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8058{
8059 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8060
8061 //Using different approach to get required WiFi Parameters from system available commands
8062#if 0
8063 FILE *f;
8064 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8065 char cmd[256], buf[2048];
8066 char *param , *value, *line=NULL;
8067 size_t len = 0;
8068 ssize_t nread;
8069 wifi_associated_dev3_t *dev=NULL;
8070 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08008071 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08008072 _syscmd(cmd,buf,sizeof(buf));
8073 *output_array_size = atoi(buf);
8074
8075 if (*output_array_size <= 0)
8076 return RETURN_OK;
8077
8078 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8079 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08008080 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08008081 _syscmd(cmd,buf,sizeof(buf));
8082 f = fopen("/tmp/connected_devices.txt", "r");
8083 if (f==NULL)
8084 {
8085 *output_array_size=0;
8086 return RETURN_ERR;
8087 }
8088 while ((nread = getline(&line, &len, f)) != -1)
8089 {
8090 param = strtok(line,"=");
8091 value = strtok(NULL,"=");
8092
8093 if( strcmp("flags",param) == 0 )
8094 {
8095 value[strlen(value)-1]='\0';
8096 if(strstr (value,"AUTHORIZED") != NULL )
8097 {
8098 dev[auth_temp].cli_AuthenticationState = 1;
8099 dev[auth_temp].cli_Active = 1;
8100 auth_temp++;
8101 read_flag=1;
8102 }
8103 }
8104 if(read_flag==1)
8105 {
8106 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8107 {
8108 value[strlen(value)-1]='\0';
8109 sscanf(value, "%x:%x:%x:%x:%x:%x",
8110 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8111 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8112 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8113 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8114 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8115 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8116
8117 }
8118 else if( strcmp("rx_packets",param) == 0 )
8119 {
8120 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8121 }
8122
8123 else if( strcmp("tx_packets",param) == 0 )
8124 {
8125 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8126 }
8127
8128 else if( strcmp("rx_bytes",param) == 0 )
8129 {
8130 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8131 }
8132
8133 else if( strcmp("tx_bytes",param) == 0 )
8134 {
8135 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8136 mac_temp++;
8137 read_flag=0;
8138 }
8139 }
8140 }
8141
8142 *output_array_size = auth_temp;
8143 auth_temp=0;
8144 mac_temp=0;
8145 free(line);
8146 fclose(f);
8147#endif
8148 char interface_name[MAX_BUF_SIZE] = {0};
8149 char wifi_status[MAX_BUF_SIZE] = {0};
8150 char hostapdconf[MAX_BUF_SIZE] = {0};
8151
8152 wifi_associated_dev3_t *dev_array = NULL;
8153 ULONG wifi_count = 0;
8154
8155 *associated_dev_array = NULL;
8156 *output_array_size = 0;
8157
8158 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8159 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8160 {
8161 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8162
developerac6f1142022-12-20 19:26:35 +08008163 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008164
8165 if(strlen(interface_name) > 1)
8166 {
8167 wifihal_interfacestatus(wifi_status,interface_name);
8168 if(strcmp(wifi_status,"RUNNING") == 0)
8169 {
8170 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8171
8172 *associated_dev_array = dev_array;
8173 *output_array_size = wifi_count;
8174 }
8175 else
8176 {
8177 *associated_dev_array = NULL;
8178 }
8179 }
8180 }
8181
8182 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8183 return RETURN_OK;
8184}
8185#endif
8186
8187/* getIPAddress function */
8188/**
8189* @description Returning IpAddress of the Matched String
8190*
8191* @param
8192* @str Having MacAddress
8193* @ipaddr Having ipaddr
8194* @return The status of the operation
8195* @retval RETURN_OK if successful
8196* @retval RETURN_ERR if any error is detected
8197*
8198*/
8199
8200INT getIPAddress(char *str,char *ipaddr)
8201{
8202 FILE *fp = NULL;
8203 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8204 int LeaseTime = 0,ret = 0;
8205 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8206 {
8207 return RETURN_ERR;
8208 }
8209
8210 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8211 {
8212 /*
8213 Sample:sss
8214 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8215 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8216 */
8217 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008218 &(LeaseTime),
8219 phyAddr,
8220 ipAddr,
8221 hostName
8222 );
developer06a01d92022-09-07 16:32:39 +08008223 if(ret != 4)
8224 continue;
8225 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008226 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008227 }
developerd946fd62022-12-08 18:03:28 +08008228 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008229 return RETURN_OK;
8230}
8231
8232/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8233/**
8234* @description Returning Inactive wireless connected clients informations
8235*
8236* @param
8237* @filename Holding private_wifi 2g/5g content files
8238* @associated_dev_array Having inactiv wireless clients informations
8239* @output_array_size Returning Inactive wireless counts
8240* @return The status of the operation
8241* @retval RETURN_OK if successful
8242* @retval RETURN_ERR if any error is detected
8243*
8244*/
8245
8246INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8247{
8248 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8249 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8250 FILE *fp = NULL;
8251 int arr[MACADDRESS_SIZE] = {0};
8252 unsigned char mac[MACADDRESS_SIZE] = {0};
8253 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8254 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8255 fp = popen(buf,"r");
8256 if(fp == NULL)
8257 return RETURN_ERR;
8258 else
8259 {
8260 fgets(path,sizeof(path),fp);
8261 maccount = atoi(path);
8262 }
8263 pclose(fp);
8264 *output_array_size = maccount;
8265 wifi_associated_dev3_t* temp = NULL;
8266 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8267 *associated_dev_array = temp;
8268 if(temp == NULL)
8269 {
8270 printf("Error Statement. Insufficient memory \n");
8271 return RETURN_ERR;
8272 }
8273 memset(buf,0,sizeof(buf));
8274 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8275 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008276 if (fp == NULL) {
8277 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8278 return RETURN_ERR;
8279 }
developer06a01d92022-09-07 16:32:39 +08008280 for(count = 0; count < maccount ; count++)
8281 {
8282 fgets(path,sizeof(path),fp);
8283 for(i = 0; path[i]!='\n';i++)
8284 str[i]=path[i];
8285 str[i]='\0';
8286 getIPAddress(str,ipaddr);
8287 memset(buf,0,sizeof(buf));
8288 if(strlen(ipaddr) > 0)
8289 {
8290 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8291 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8292 {
8293 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8294 {
8295 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8296 {
8297 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8298
8299 }
8300 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8301 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]);
8302 }
8303 temp[count].cli_AuthenticationState = 0; //TODO
8304 temp[count].cli_Active = 0; //TODO
8305 temp[count].cli_SignalStrength = 0;
8306 }
8307 else //Active wireless clients info
8308 {
8309 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8310 {
8311 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8312 {
8313 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8314
8315 }
8316 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8317 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]);
8318 }
8319 temp[count].cli_Active = 1;
8320 }
8321 }
8322 memset(ipaddr,0,sizeof(ipaddr));
8323 }
8324 pclose(fp);
8325 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8326 return RETURN_OK;
8327}
8328//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8329//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8330//To get Band Steering Capability
8331INT wifi_getBandSteeringCapability(BOOL *support)
8332{
8333 *support = FALSE;
8334 return RETURN_OK;
8335}
8336
8337
8338//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8339//To get Band Steering enable status
8340INT wifi_getBandSteeringEnable(BOOL *enable)
8341{
8342 *enable = FALSE;
8343 return RETURN_OK;
8344}
8345
8346//To turn on/off Band steering
8347INT wifi_setBandSteeringEnable(BOOL enable)
8348{
8349 return RETURN_OK;
8350}
8351
8352//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8353//To get Band Steering AP group
8354INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8355{
8356 if (NULL == output_ApGroup)
8357 return RETURN_ERR;
8358
8359 strcpy(output_ApGroup, "1,2");
8360 return RETURN_OK;
8361}
8362
8363//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8364//to set and read the band steering BandUtilizationThreshold parameters
8365INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8366{
8367 return RETURN_ERR;
8368}
8369
8370INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8371{
8372 return RETURN_ERR;
8373}
8374
8375//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8376//to set and read the band steering RSSIThreshold parameters
8377INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8378{
8379 return RETURN_ERR;
8380}
8381
8382INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8383{
8384 return RETURN_ERR;
8385}
8386
8387
8388//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8389//to set and read the band steering physical modulation rate threshold parameters
8390INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8391{
8392 //If chip is not support, return -1
8393 return RETURN_ERR;
8394}
8395
8396INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8397{
8398 //If chip is not support, return -1
8399 return RETURN_ERR;
8400}
8401
8402//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8403//to set and read the inactivity time (in seconds) for steering under overload condition
8404INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8405{
8406 return RETURN_ERR;
8407}
8408
8409INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8410{
8411 return RETURN_ERR;
8412}
8413
8414//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8415//to set and read the inactivity time (in seconds) for steering under Idle condition
8416INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8417{
8418 return RETURN_ERR;
8419}
8420
8421INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8422{
8423 return RETURN_ERR;
8424}
8425
8426//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8427//pClientMAC[64]
8428//pSourceSSIDIndex[64]
8429//pDestSSIDIndex[64]
8430//pSteeringReason[256]
8431INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8432{
8433 //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
8434 *pSteeringTime=time(NULL);
8435 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8436 return RETURN_OK;
8437}
8438
8439INT wifi_ifConfigDown(INT apIndex)
8440{
8441 INT status = RETURN_OK;
8442 char cmd[64];
8443
8444 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8445 printf("%s: %s\n", __func__, cmd);
8446 system(cmd);
8447
8448 return status;
8449}
8450
8451INT wifi_ifConfigUp(INT apIndex)
8452{
developerd946fd62022-12-08 18:03:28 +08008453 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008454 char cmd[128];
8455 char buf[1024];
8456
developerac6f1142022-12-20 19:26:35 +08008457 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008458 return RETURN_ERR;
8459 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008460 _syscmd(cmd, buf, sizeof(buf));
8461 return 0;
8462}
8463
8464//>> Deprecated. Replace with wifi_applyRadioSettings
8465INT wifi_pushBridgeInfo(INT apIndex)
8466{
developerd946fd62022-12-08 18:03:28 +08008467 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008468 char ip[32] = {0};
8469 char subnet[32] = {0};
8470 char bridge[32] = {0};
8471 int vlanId = 0;
8472 char cmd[128] = {0};
8473 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008474
8475 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8476 wifi_getApVlanID(apIndex,&vlanId);
8477
developerac6f1142022-12-20 19:26:35 +08008478 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008479 return RETURN_ERR;
8480 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008481 _syscmd(cmd,buf, sizeof(buf));
8482
8483 return 0;
8484}
8485
8486INT wifi_pushChannel(INT radioIndex, UINT channel)
8487{
developerd946fd62022-12-08 18:03:28 +08008488 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008489 char cmd[128];
8490 char buf[1024];
8491 int apIndex;
8492
8493 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008494 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008495 return RETURN_ERR;
8496 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008497 _syscmd(cmd,buf, sizeof(buf));
8498
8499 return 0;
8500}
8501
8502INT wifi_pushChannelMode(INT radioIndex)
8503{
8504 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8505 return RETURN_ERR;
8506}
8507
8508INT wifi_pushDefaultValues(INT radioIndex)
8509{
8510 //Apply Comcast specified default radio settings instantly
8511 //AMPDU=1
8512 //AMPDUFrames=32
8513 //AMPDULim=50000
8514 //txqueuelen=1000
8515
8516 return RETURN_ERR;
8517}
8518
8519INT wifi_pushTxChainMask(INT radioIndex)
8520{
8521 //Apply default TxChainMask instantly
8522 return RETURN_ERR;
8523}
8524
8525INT wifi_pushRxChainMask(INT radioIndex)
8526{
8527 //Apply default RxChainMask instantly
8528 return RETURN_ERR;
8529}
8530
8531INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8532{
8533 INT status;
8534
8535 status = wifi_setSSIDName(apIndex,ssid);
8536 wifi_setApEnable(apIndex,FALSE);
8537 wifi_setApEnable(apIndex,TRUE);
8538
8539 return status;
8540}
8541
8542INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8543{
8544 //Apply default Ssid Advertisement instantly
8545 return RETURN_ERR;
8546}
8547
8548INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8549{
8550 INT status = RETURN_ERR;
8551 *output = 0;
8552 return RETURN_ERR;
8553}
8554
8555INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8556{
8557 return RETURN_OK;
8558}
8559
8560INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8561{
8562 return RETURN_OK;
8563}
8564
8565//To-do
8566INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8567{
developereb199ae2022-09-13 14:04:27 +08008568 char output[16]={'\0'};
8569 char config_file[MAX_BUF_SIZE] = {0};
8570
8571 if (!output_string)
8572 return RETURN_ERR;
8573
8574 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8575 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8576
8577 if (strlen(output) == 0)
8578 snprintf(output_string, 64, "Disabled");
8579 else if (strncmp(output, "0", 1) == 0)
8580 snprintf(output_string, 64, "Disabled");
8581 else if (strncmp(output, "1", 1) == 0)
8582 snprintf(output_string, 64, "Optional");
8583 else if (strncmp(output, "2", 1) == 0)
8584 snprintf(output_string, 64, "Required");
8585 else {
8586 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8587 return RETURN_ERR;
8588 }
8589
8590 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008591 return RETURN_OK;
8592}
8593INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8594{
developereb199ae2022-09-13 14:04:27 +08008595 char str[MAX_BUF_SIZE]={'\0'};
8596 char cmd[MAX_CMD_SIZE]={'\0'};
8597 struct params params;
8598 char config_file[MAX_BUF_SIZE] = {0};
8599
8600 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8601 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8602 return RETURN_ERR;
8603
8604 params.name = "ieee80211w";
8605 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8606 params.value = "0";
8607 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8608 params.value = "1";
8609 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8610 params.value = "2";
8611 else{
8612 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8613 return RETURN_ERR;
8614 }
8615 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8616 wifi_hostapdWrite(config_file, &params, 1);
8617 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008618 return RETURN_OK;
8619}
8620INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8621{
8622 char output[16]={'\0'};
8623 char config_file[MAX_BUF_SIZE] = {0};
8624
8625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8626 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8627 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8628
8629 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8630 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8631
8632 return RETURN_OK;
8633}
8634
8635INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8636{
8637 return RETURN_OK;
8638}
8639
8640INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8641{
8642 return RETURN_OK;
8643}
8644
8645INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8646{
8647 return RETURN_OK;
8648}
8649
8650INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8651{
8652 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8653 char config_file[MAX_BUF_SIZE] = {0};
8654
8655 if (NULL == output)
8656 return RETURN_ERR;
8657 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8658 wifi_hostapdRead(config_file,"hw_mode",output,64);
8659
8660 if(strcmp(output,"b")==0)
8661 sprintf(output, "%s", "1,2,5.5,11");
8662 else if (strcmp(output,"a")==0)
8663 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8664 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8665 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8666
8667 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8668 return RETURN_OK;
8669}
8670
8671INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8672{
8673 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8674 char *temp;
8675 char temp_output[128];
8676 char temp_TransmitRates[128];
8677 char config_file[MAX_BUF_SIZE] = {0};
8678
8679 if (NULL == output)
8680 return RETURN_ERR;
8681
8682 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8683 wifi_hostapdRead(config_file,"supported_rates",output,64);
8684
developer5b398df2022-11-17 20:39:48 +08008685 if (strlen(output) == 0) {
8686 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8687 return RETURN_OK;
8688 }
developer06a01d92022-09-07 16:32:39 +08008689 strcpy(temp_TransmitRates,output);
8690 strcpy(temp_output,"");
8691 temp = strtok(temp_TransmitRates," ");
8692 while(temp!=NULL)
8693 {
8694 temp[strlen(temp)-1]=0;
8695 if((temp[0]=='5') && (temp[1]=='\0'))
8696 {
8697 temp="5.5";
8698 }
8699 strcat(temp_output,temp);
8700 temp = strtok(NULL," ");
8701 if(temp!=NULL)
8702 {
8703 strcat(temp_output,",");
8704 }
8705 }
8706 strcpy(output,temp_output);
8707 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8708
8709 return RETURN_OK;
8710}
8711
8712INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8713{
8714 return RETURN_OK;
8715}
8716
8717
8718INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8719{
8720 int i=0;
8721 char *temp;
developeref938762022-10-19 17:21:01 +08008722 char temp1[128] = {0};
8723 char temp_output[128] = {0};
8724 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008725 struct params params={'\0'};
8726 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008727 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008728
8729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8730 if(NULL == output)
8731 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008732 strcpy(temp_TransmitRates,output);
8733
8734 for(i=0;i<strlen(temp_TransmitRates);i++)
8735 {
developeref938762022-10-19 17:21:01 +08008736 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008737 {
8738 continue;
8739 }
8740 else
8741 {
8742 return RETURN_ERR;
8743 }
8744 }
8745 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008746 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008747 while(temp!=NULL)
8748 {
8749 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008750 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008751 {
developeref938762022-10-19 17:21:01 +08008752 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008753 {
8754 return RETURN_ERR;
8755 }
8756 }
8757
8758 if(strcmp(temp,"5.5")==0)
8759 {
8760 strcpy(temp1,"55");
8761 }
8762 else
8763 {
8764 strcat(temp1,"0");
8765 }
8766 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008767 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008768 if(temp!=NULL)
8769 {
8770 strcat(temp_output," ");
8771 }
8772 }
8773 strcpy(output,temp_output);
8774
developer06a01d92022-09-07 16:32:39 +08008775 params.name = "supported_rates";
8776 params.value = output;
8777
8778 wifi_dbg_printf("\n%s:",__func__);
8779 wifi_dbg_printf("params.value=%s\n",params.value);
8780 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8781 wifi_hostapdWrite(config_file,&params,1);
8782 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8783
8784 return RETURN_OK;
8785}
8786
8787
8788static char *sncopy(char *dst, int dst_sz, const char *src)
8789{
8790 if (src && dst && dst_sz > 0) {
8791 strncpy(dst, src, dst_sz);
8792 dst[dst_sz - 1] = '\0';
8793 }
8794 return dst;
8795}
8796
8797static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8798{
8799 if (0 == strcmp(ht_mode, "HT40") ||
8800 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008801 0 == strcmp(ht_mode, "HT160") ||
8802 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008803 switch (channel) {
developer9a520b12023-09-21 16:01:43 +08008804 case 0 ... 7:
developer06a01d92022-09-07 16:32:39 +08008805 case 36:
8806 case 44:
8807 case 52:
8808 case 60:
8809 case 100:
8810 case 108:
8811 case 116:
8812 case 124:
8813 case 132:
8814 case 140:
8815 case 149:
8816 case 157:
8817 return 1;
8818 case 8 ... 13:
8819 case 40:
8820 case 48:
8821 case 56:
8822 case 64:
8823 case 104:
8824 case 112:
8825 case 120:
8826 case 128:
8827 case 136:
8828 case 144:
8829 case 153:
8830 case 161:
8831 return -1;
8832 default:
8833 return -EINVAL;
8834 }
8835 }
8836
8837 return -EINVAL;
8838}
8839
developerb7593de2022-10-18 09:51:57 +08008840static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8841{
8842 int idx = channel%8;
8843 if (0 == strcmp(ht_mode, "HT40") ||
8844 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008845 0 == strcmp(ht_mode, "HT160") ||
8846 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008847 switch (idx) {
8848 case 1:
8849 return 1;
8850 case 5:
8851 return -1;
8852 default:
8853 return -EINVAL;
8854 }
8855 }
8856
8857 return -EINVAL;
8858}
developer06a01d92022-09-07 16:32:39 +08008859static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8860{
8861 if (NULL == hw_mode) return;
8862
8863 if (0 == strcmp(hw_mode, "ac"))
8864 sncopy(bw_mode, bw_mode_len, "ht vht");
8865
8866 if (0 == strcmp(hw_mode, "n"))
8867 sncopy(bw_mode, bw_mode_len, "ht");
8868
8869 return;
8870}
8871
8872static int util_chan_to_freq(int chan)
8873{
8874 if (chan == 14)
8875 return 2484;
8876 else if (chan < 14)
8877 return 2407 + chan * 5;
8878 else if (chan >= 182 && chan <= 196)
8879 return 4000 + chan * 5;
8880 else
8881 return 5000 + chan * 5;
8882 return 0;
8883}
8884
developerb7593de2022-10-18 09:51:57 +08008885static int util_6G_chan_to_freq(int chan)
8886{
8887 if (chan)
8888 return 5950 + chan * 5;
8889 else
8890 return 0;
8891
8892}
developer06a01d92022-09-07 16:32:39 +08008893const int *util_unii_5g_chan2list(int chan, int width)
8894{
8895 static const int lists[] = {
8896 // <width>, <chan1>, <chan2>..., 0,
developer8b2f01f2024-03-01 14:50:27 +08008897 20, 36, 0,
8898 20, 40, 0,
8899 20, 44, 0,
8900 20, 48, 0,
8901 20, 52, 0,
8902 20, 56, 0,
8903 20, 60, 0,
8904 20, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008905 20, 100, 0,
8906 20, 104, 0,
8907 20, 108, 0,
8908 20, 112, 0,
8909 20, 116, 0,
8910 20, 120, 0,
8911 20, 124, 0,
8912 20, 128, 0,
8913 20, 132, 0,
8914 20, 136, 0,
8915 20, 140, 0,
8916 20, 144, 0,
8917 20, 149, 0,
8918 20, 153, 0,
8919 20, 157, 0,
8920 20, 161, 0,
8921 20, 165, 0,
developer8b2f01f2024-03-01 14:50:27 +08008922 20, 169, 0,
8923 20, 173, 0,
8924 20, 177, 0,
8925 40, 36, 40, 0,
8926 40, 44, 48, 0,
8927 40, 52, 56, 0,
8928 40, 60, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008929 40, 100, 104, 0,
8930 40, 108, 112, 0,
8931 40, 116, 120, 0,
8932 40, 124, 128, 0,
8933 40, 132, 136, 0,
8934 40, 140, 144, 0,
8935 40, 149, 153, 0,
8936 40, 157, 161, 0,
developer8b2f01f2024-03-01 14:50:27 +08008937 40, 165, 169, 0,
8938 40, 173, 177, 0,
8939 80, 36, 40, 44, 48, 0,
8940 80, 52, 56, 60, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008941 80, 100, 104, 108, 112, 0,
8942 80, 116, 120, 124, 128, 0,
8943 80, 132, 136, 140, 144, 0,
8944 80, 149, 153, 157, 161, 0,
developer8b2f01f2024-03-01 14:50:27 +08008945 80, 165, 169, 173, 177, 0,
8946 160,36, 40, 44, 48, 52, 56, 60, 64, 0,
8947 160,100, 104, 108, 112, 116, 120, 124, 128, 0,
8948 160,149, 153, 157, 161, 165, 169, 173, 177, 0,
developer06a01d92022-09-07 16:32:39 +08008949 -1 // final delimiter
8950 };
8951 const int *start;
8952 const int *p;
8953
8954 for (p = lists; *p != -1; p++) {
8955 if (*p == width) {
8956 for (start = ++p; *p != 0; p++) {
8957 if (*p == chan)
8958 return start;
8959 }
8960 }
8961 // move to the end of channel list of given width
8962 while (*p != 0) {
8963 p++;
8964 }
8965 }
8966
8967 return NULL;
8968}
8969
8970static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8971{
8972 if (NULL == ht_mode)
8973 return 0;
8974
8975 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8976 const int *chans = util_unii_5g_chan2list(channel, width);
8977 int sum = 0;
8978 int cnt = 0;
8979
8980 if (NULL == chans)
8981 return 0;
8982
8983 while (*chans) {
8984 sum += *chans;
8985 cnt++;
8986 chans++;
8987 }
developer30423732022-12-01 16:17:49 +08008988 if (cnt == 0)
8989 return 0;
developer06a01d92022-09-07 16:32:39 +08008990 return sum / cnt;
8991}
8992
developerb7593de2022-10-18 09:51:57 +08008993static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8994{
8995 if (NULL == ht_mode)
8996 return 0;
8997
8998 int width = strtol((ht_mode + 2), NULL, 10);
8999
9000 int idx = 0 ;
9001 int centerchan = 0;
9002 int chan_ofs = 1;
9003
9004 if (width == 40){
9005 idx = ((channel/4) + chan_ofs)%2;
9006 switch (idx) {
9007 case 0:
9008 centerchan = (channel - 2);
9009 break;
9010 case 1:
9011 centerchan = (channel + 2);
9012 break;
9013 default:
9014 return -EINVAL;
9015 }
9016 }else if (width == 80){
9017 idx = ((channel/4) + chan_ofs)%4;
9018 switch (idx) {
9019 case 0:
9020 centerchan = (channel - 6);
9021 break;
9022 case 1:
9023 centerchan = (channel + 6);
9024 break;
9025 case 2:
9026 centerchan = (channel + 2);
9027 break;
9028 case 3:
9029 centerchan = (channel - 2);
9030 break;
9031 default:
9032 return -EINVAL;
9033 }
9034 }else if (width == 160){
9035 switch (channel) {
9036 case 1 ... 29:
9037 centerchan = 15;
9038 break;
9039 case 33 ... 61:
9040 centerchan = 47;
9041 break;
9042 case 65 ... 93:
9043 centerchan = 79;
9044 break;
9045 case 97 ... 125:
9046 centerchan = 111;
9047 break;
9048 case 129 ... 157:
9049 centerchan = 143;
9050 break;
9051 case 161 ... 189:
9052 centerchan = 175;
9053 break;
9054 case 193 ... 221:
9055 centerchan = 207;
9056 break;
9057 default:
9058 return -EINVAL;
9059 }
developer7c4cd202023-03-01 10:56:29 +08009060 }else if (width == 320){
9061 switch (channel) {
9062 case 1 ... 29:
9063 centerchan = 31;
9064 break;
9065 case 33 ... 93:
9066 centerchan = 63;
9067 break;
9068 case 97 ... 157:
9069 centerchan = 127;
9070 break;
9071 case 161 ... 221:
9072 centerchan = 191;
9073 break;
9074 default:
9075 return -EINVAL;
9076 }
developerb7593de2022-10-18 09:51:57 +08009077 }
9078 return centerchan;
9079}
developer06a01d92022-09-07 16:32:39 +08009080static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9081{
9082 BOOL onlyG, onlyN, onlyA;
9083 CHAR tmp[64];
9084 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9085 if (ret == RETURN_OK) {
9086 sncopy(hw_mode, hw_mode_size, tmp);
9087 }
9088 return ret;
9089}
9090
9091INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9092{
9093 // Sample commands:
9094 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9095 // hostapd_cli -i wifi0 chan_switch 30 2437
9096 char cmd[MAX_CMD_SIZE] = {0};
9097 char buf[MAX_BUF_SIZE] = {0};
9098 int freq = 0, ret = 0;
9099 char center_freq1_str[32] = ""; // center_freq1=%d
9100 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9101 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9102 char hw_mode[16] = ""; // n|ac
9103 char bw_mode[16] = ""; // ht|ht vht
9104 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08009105 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009106 int sec_chan_offset;
9107 int width;
developer4fb0b922022-09-30 14:29:09 +08009108 char config_file[64] = {0};
9109 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08009110 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08009111 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08009112 wifi_band band = band_invalid;
9113 int center_chan = 0;
9114 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08009115
developer4fb0b922022-09-30 14:29:09 +08009116 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08009117
developerac6f1142022-12-20 19:26:35 +08009118 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009119 return RETURN_ERR;
9120
developer06a01d92022-09-07 16:32:39 +08009121 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9122
developerb7593de2022-10-18 09:51:57 +08009123 band = wifi_index_to_band(radioIndex);
9124
developer5884e982022-10-06 10:52:50 +08009125 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08009126
9127 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08009128 if (channel){
developerb7593de2022-10-18 09:51:57 +08009129 if (band == band_6){
9130 freq = util_6G_chan_to_freq(channel);
9131 }else{
9132 freq = util_chan_to_freq(channel);
9133 }
developer7c4cd202023-03-01 10:56:29 +08009134 if (width == 320) {
9135 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
9136 setEHT320 = TRUE;
9137 }
developer5884e982022-10-06 10:52:50 +08009138 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08009139
developer5884e982022-10-06 10:52:50 +08009140 // Provide bandwith if specified
9141 if (channel_width_MHz > 20) {
9142 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9143 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9144 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08009145
developer5884e982022-10-06 10:52:50 +08009146 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9147 }else if (channel_width_MHz == 20){
9148 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9149 }
developer06a01d92022-09-07 16:32:39 +08009150
developerb7593de2022-10-18 09:51:57 +08009151
developer5884e982022-10-06 10:52:50 +08009152 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08009153 if (band == band_6){
9154 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9155 if(center_chan){
9156 center_freq1 = util_6G_chan_to_freq(center_chan);
9157 }
9158 }else{
9159 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9160 if(center_chan){
9161 center_freq1 = util_chan_to_freq(center_chan);
9162 }
developer5884e982022-10-06 10:52:50 +08009163 }
developerb7593de2022-10-18 09:51:57 +08009164
9165 if (center_freq1)
9166 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9167
9168 }
9169
9170 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9171 if (band == band_6){
9172 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9173 }else{
9174 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009175 }
developerb7593de2022-10-18 09:51:57 +08009176 if (sec_chan_offset != -EINVAL)
9177 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009178
developer5884e982022-10-06 10:52:50 +08009179 // Only the first AP, other are hanging on the same radio
9180 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009181 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9182 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009183 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9184 wifi_dbg_printf("execute: '%s'\n", cmd);
9185 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009186 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009187
developer5884e982022-10-06 10:52:50 +08009188 ret = wifi_setRadioChannel(radioIndex, channel);
9189 if (ret != RETURN_OK) {
9190 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9191 return RETURN_ERR;
9192 }
9193
9194 if (sec_chan_offset == 1) ext_str = "Above";
9195 else if (sec_chan_offset == -1) ext_str = "Below";
9196
9197 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009198
developer5884e982022-10-06 10:52:50 +08009199 } else {
9200 if (channel_width_MHz > 20)
9201 ext_str = "Above";
9202 }
developer4fb0b922022-09-30 14:29:09 +08009203
developer06a01d92022-09-07 16:32:39 +08009204 char mhz_str[16];
9205 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009206 if (setEHT320 == TRUE)
9207 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9208 else
9209 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009210
developer57fa24a2023-03-15 17:25:07 +08009211 writeBandWidth(radioIndex, mhz_str);
9212 if (band == band_2_4 || band == band_5) {
9213 if (width == 20)
9214 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9215 else
9216 wifi_setRadioExtChannel(radioIndex, ext_str);
9217 }
developer06a01d92022-09-07 16:32:39 +08009218 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9219
9220 return RETURN_OK;
9221}
9222
9223INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9224{
developer615510b2022-09-27 10:14:35 +08009225 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009226 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009227 char cmd[256]={0};
9228 char buf[128]={0};
9229 char file_name[32] = {0};
9230 char filter_SSID[32] = {0};
9231 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009232 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009233 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009234 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009235 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009236 size_t len=0;
9237 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009238 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009239 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009240 bool filter_enable = false;
9241 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009242 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009243
developer615510b2022-09-27 10:14:35 +08009244 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009245
developer615510b2022-09-27 10:14:35 +08009246 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9247 f = fopen(file_name, "r");
9248 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009249 fgets(buf, sizeof(file_name), f);
9250 if ((strncmp(buf, "0", 1)) != 0) {
9251 fgets(filter_SSID, sizeof(file_name), f);
9252 if (strlen(filter_SSID) != 0)
9253 filter_enable = true;
9254 }
developer615510b2022-09-27 10:14:35 +08009255 fclose(f);
9256 }
9257
developerac6f1142022-12-20 19:26:35 +08009258 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009259 return RETURN_ERR;
9260
developer033b37b2022-10-18 11:27:46 +08009261 phyId = radio_index_to_phy(radio_index);
9262
9263 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009264 _syscmd(cmd, buf, sizeof(buf));
9265 channels_num = strtol(buf, NULL, 10);
9266
developerd946fd62022-12-08 18:03:28 +08009267 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9268 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
developer615510b2022-09-27 10:14:35 +08009269 fprintf(stderr, "cmd: %s\n", cmd);
9270 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009271 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9272 return RETURN_ERR;
9273 }
developer5550e242022-09-30 09:59:32 +08009274
9275 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9276 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9277
developer615510b2022-09-27 10:14:35 +08009278 ret = fgets(line, sizeof(line), f);
9279 while (ret != NULL) {
9280 if(strstr(line, "BSS") != NULL) { // new neighbor info
9281 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9282 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9283 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9284
9285 if (!filter_BSS) {
9286 index++;
9287 wifi_neighbor_ap2_t *tmp;
9288 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9289 if (tmp == NULL) { // no more memory to use
9290 index--;
9291 wifi_dbg_printf("%s: realloc failed\n", __func__);
9292 break;
9293 }
9294 scan_array = tmp;
9295 }
9296 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009297
developer615510b2022-09-27 10:14:35 +08009298 filter_BSS = false;
9299 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9300 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9301 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9302 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9303 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009304 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009305 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009306
developer615510b2022-09-27 10:14:35 +08009307 if (freq >= 2412 && freq <= 2484) {
9308 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9309 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9310 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9311 }
9312 else if (freq >= 5160 && freq <= 5805) {
9313 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9314 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9315 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9316 }
developer06a01d92022-09-07 16:32:39 +08009317
developer615510b2022-09-27 10:14:35 +08009318 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009319 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009320 for (int i = 0; i < channels_num; i++) {
9321 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9322 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9323 break;
9324 }
9325 }
developer06a01d92022-09-07 16:32:39 +08009326 }
developer615510b2022-09-27 10:14:35 +08009327 } else if (strstr(line, "beacon interval") != NULL) {
9328 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9329 } else if (strstr(line, "signal") != NULL) {
9330 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9331 } else if (strstr(line,"SSID") != NULL) {
9332 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9333 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9334 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009335 }
developer615510b2022-09-27 10:14:35 +08009336 } else if (strstr(line, "Supported rates") != NULL) {
9337 char SRate[80] = {0}, *tmp = NULL;
9338 memset(buf, 0, sizeof(buf));
9339 strcpy(SRate, line);
9340 tmp = strtok(SRate, ":");
9341 tmp = strtok(NULL, ":");
9342 strcpy(buf, tmp);
9343 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009344
developer615510b2022-09-27 10:14:35 +08009345 tmp = strtok(buf, " \n");
9346 while (tmp != NULL) {
9347 strcat(SRate, tmp);
9348 if (SRate[strlen(SRate) - 1] == '*') {
9349 SRate[strlen(SRate) - 1] = '\0';
9350 }
9351 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009352
developer615510b2022-09-27 10:14:35 +08009353 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009354 }
developer615510b2022-09-27 10:14:35 +08009355 SRate[strlen(SRate) - 1] = '\0';
9356 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9357 } else if (strstr(line, "DTIM") != NULL) {
9358 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9359 } else if (strstr(line, "VHT capabilities") != NULL) {
9360 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9361 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9362 } else if (strstr(line, "HT capabilities") != NULL) {
9363 strcat(scan_array[index].ap_SupportedStandards, ",n");
9364 strcpy(scan_array[index].ap_OperatingStandards, "n");
9365 } else if (strstr(line, "VHT operation") != NULL) {
9366 ret = fgets(line, sizeof(line), f);
9367 sscanf(line," * channel width: %d", &vht_channel_width);
9368 if(vht_channel_width == 1) {
9369 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9370 } else {
9371 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9372 }
9373 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9374 continue;
9375 } else if (strstr(line, "HT operation") != NULL) {
9376 ret = fgets(line, sizeof(line), f);
9377 sscanf(line," * secondary channel offset: %s", &buf);
9378 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009379 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009380 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 +08009381 }
developer615510b2022-09-27 10:14:35 +08009382 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009383 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009384 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9385 } else {
9386 //20Mhz
9387 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 +08009388 }
developer615510b2022-09-27 10:14:35 +08009389 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009390 continue;
developer615510b2022-09-27 10:14:35 +08009391 } else if (strstr(line, "HE capabilities") != NULL) {
9392 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9393 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9394 ret = fgets(line, sizeof(line), f);
9395 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9396 if (strstr(line, "HE40/2.4GHz") != NULL)
9397 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9398 else
9399 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9400 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9401 if (strstr(line, "HE80/5GHz") != NULL) {
9402 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9403 ret = fgets(line, sizeof(line), f);
9404 } else
9405 continue;
9406 if (strstr(line, "HE160/5GHz") != NULL)
9407 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009408 }
developer615510b2022-09-27 10:14:35 +08009409 continue;
9410 } else if (strstr(line, "WPA") != NULL) {
9411 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9412 } else if (strstr(line, "RSN") != NULL) {
9413 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9414 } else if (strstr(line, "Group cipher") != NULL) {
9415 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9416 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9417 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009418 }
developer06a01d92022-09-07 16:32:39 +08009419 }
developer615510b2022-09-27 10:14:35 +08009420 ret = fgets(line, sizeof(line), f);
9421 }
9422
9423 if (!filter_BSS) {
9424 *output_array_size = index + 1;
9425 } else {
9426 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9427 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009428 }
developer06a01d92022-09-07 16:32:39 +08009429 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009430 pclose(f);
developer5550e242022-09-30 09:59:32 +08009431 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009432 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009433 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009434}
developer615510b2022-09-27 10:14:35 +08009435
developer06a01d92022-09-07 16:32:39 +08009436INT wifi_getApAssociatedDeviceStats(
9437 INT apIndex,
9438 mac_address_t *clientMacAddress,
9439 wifi_associated_dev_stats_t *associated_dev_stats,
9440 u64 *handle)
9441{
9442 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9443 char interface_name[50] = {0};
9444 char cmd[1024] = {0};
9445 char mac_str[18] = {0};
9446 char *key = NULL;
9447 char *val = NULL;
9448 FILE *f = NULL;
9449 char *line = NULL;
9450 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009451
9452 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9453 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9454 return RETURN_ERR;
9455 }
9456
9457 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9458 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9459 if((f = popen(cmd, "r")) == NULL) {
9460 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9461 return RETURN_ERR;
9462 }
9463
developer30423732022-12-01 16:17:49 +08009464 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009465 key = strtok(line,":");
9466 val = strtok(NULL,":");
9467
9468 if(!strncmp(key,"rx bytes",8))
9469 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9470 if(!strncmp(key,"tx bytes",8))
9471 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9472 if(!strncmp(key,"rx packets",10))
9473 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9474 if(!strncmp(key,"tx packets",10))
9475 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9476 if(!strncmp(key,"tx retries",10))
9477 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9478 if(!strncmp(key,"tx failed",9))
9479 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9480 if(!strncmp(key,"rx drop misc",13))
9481 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9482 if(!strncmp(key,"rx bitrate",10)) {
9483 val = strtok(val, " ");
9484 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9485 }
9486 if(!strncmp(key,"tx bitrate",10)) {
9487 val = strtok(val, " ");
9488 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9489 }
9490 }
9491 free(line);
9492 pclose(f);
9493 return RETURN_OK;
9494}
9495
9496INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9497{
developerd946fd62022-12-08 18:03:28 +08009498 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009499 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9500
9501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9502 if (NULL == output_string)
9503 return RETURN_ERR;
9504
developerac6f1142022-12-20 19:26:35 +08009505 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009506 return RETURN_ERR;
9507 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08009508 _syscmd(cmd, buf, sizeof(buf));
9509
9510 //size of SSID name restricted to value less than 32 bytes
9511 snprintf(output_string, 32, "%s", buf);
9512 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9513
9514 return RETURN_OK;
9515}
9516
9517INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9518{
9519 //char cmd[MAX_CMD_SIZE] = {0};
9520 char config_file[MAX_BUF_SIZE] = {0};
9521 char buf[32] = {0};
9522
9523 if (!output_filterMode)
9524 return RETURN_ERR;
9525
9526 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9527 //_syscmd(cmd, buf, sizeof(buf));
9528 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08009529 if (!syn_flag)
9530 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
9531 else
developer07ded1f2024-01-10 10:30:15 +08009532 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer10adcc12022-09-13 14:39:17 +08009533 if(strlen(buf) == 0) {
9534 *output_filterMode = 0;
9535 }
9536 else {
9537 int macaddr_acl_mode = strtol(buf, NULL, 10);
9538 if (macaddr_acl_mode == 1) {
9539 *output_filterMode = 1;
9540 } else if (macaddr_acl_mode == 0) {
9541 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9542 if (strlen(buf) == 0) {
9543 *output_filterMode = 0;
9544 } else {
9545 *output_filterMode = 2;
9546 }
9547 } else {
9548 return RETURN_ERR;
9549 }
9550 }
developer06a01d92022-09-07 16:32:39 +08009551
9552 return RETURN_OK;
9553}
9554
9555INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9556{
9557 FILE *fp = NULL;
9558 char str[MAX_BUF_SIZE] = {0};
9559 int wificlientindex = 0 ;
9560 int count = 0;
9561 int signalstrength = 0;
9562 int arr[MACADDRESS_SIZE] = {0};
9563 unsigned char mac[MACADDRESS_SIZE] = {0};
9564 UINT wifi_count = 0;
9565 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9566 char pipeCmd[MAX_CMD_SIZE] = {0};
9567
9568 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9569 *output_array_size = 0;
9570 *associated_dev_array = NULL;
9571 char interface_name[50] = {0};
9572
9573 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9574 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9575 return RETURN_ERR;
9576 }
9577
9578 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9579 fp = popen(pipeCmd, "r");
9580 if (fp == NULL)
9581 {
9582 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9583 return RETURN_ERR;
9584 }
9585
9586 /* Read the output a line at a time - output it. */
9587 fgets(str, sizeof(str)-1, fp);
9588 wifi_count = (unsigned int) atoi ( str );
9589 *output_array_size = wifi_count;
9590 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9591 pclose(fp);
9592
9593 if(wifi_count == 0)
9594 {
9595 return RETURN_OK;
9596 }
9597 else
9598 {
9599 wifi_associated_dev2_t* temp = NULL;
9600 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9601 *associated_dev_array = temp;
9602 if(temp == NULL)
9603 {
9604 printf("Error Statement. Insufficient memory \n");
9605 return RETURN_ERR;
9606 }
9607
9608 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9609 system(pipeCmd);
9610
9611 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9612 if(fp == NULL)
9613 {
9614 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9615 return RETURN_ERR;
9616 }
9617 fclose(fp);
9618
developer30423732022-12-01 16:17:49 +08009619 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009620 fp = popen(pipeCmd, "r");
9621 if(fp)
9622 {
9623 for(count =0 ; count < wifi_count; count++)
9624 {
9625 fgets(str, MAX_BUF_SIZE, fp);
9626 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9627 {
9628 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9629 {
9630 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9631
9632 }
9633 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9634 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]);
9635 }
9636 temp[count].cli_AuthenticationState = 1; //TODO
9637 temp[count].cli_Active = 1; //TODO
9638 }
9639 pclose(fp);
9640 }
9641
9642 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009643 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
developer06a01d92022-09-07 16:32:39 +08009644 fp = popen(pipeCmd, "r");
9645 if(fp)
9646 {
9647 pclose(fp);
9648 }
9649 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9650 if(fp)
9651 {
9652 for(count =0 ; count < wifi_count ;count++)
9653 {
9654 fgets(str, MAX_BUF_SIZE, fp);
9655 signalstrength = atoi(str);
9656 temp[count].cli_RSSI = signalstrength;
9657 }
9658 pclose(fp);
9659 }
9660
9661
9662 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009663 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
developer06a01d92022-09-07 16:32:39 +08009664 fp = popen(pipeCmd, "r");
9665 if (fp)
9666 {
9667 pclose(fp);
9668 }
9669 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9670 if (fp)
9671 {
9672 for (count = 0; count < wifi_count; count++)
9673 {
9674 fgets(str, MAX_BUF_SIZE, fp);
9675 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9676 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9677 }
9678 pclose(fp);
9679 }
9680
9681 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009682 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
developer06a01d92022-09-07 16:32:39 +08009683 fp = popen(pipeCmd, "r");
9684 if (fp)
9685 {
9686 pclose(fp);
9687 }
9688 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9689 if (fp)
9690 {
9691 for (count = 0; count < wifi_count; count++)
9692 {
9693 fgets(str, MAX_BUF_SIZE, fp);
9694 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9695 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9696 }
9697 pclose(fp);
9698 }
9699 }
9700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9701 return RETURN_OK;
9702
9703}
9704
9705INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9706{
9707#if 0
9708 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009709 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009710 _syscmd(cmd, buf, sizeof(buf));*/
9711
9712 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9713 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9714 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9715 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9716
9717 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.
9718 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].
9719 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].
9720 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].
9721 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9722 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9723
9724 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9725 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9726 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9727 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.
9728 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.
9729 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.
9730 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.
9731 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.
9732 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.
9733 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.
9734 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9735#endif
9736
9737 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009738 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009739 char pipeCmd[128] = {0};
9740 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009741 wifi_ssidTrafficStats2_t *out = output_struct;
9742
developerce736392022-09-13 15:24:34 +08009743 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009744 if (!output_struct)
9745 return RETURN_ERR;
9746
developerce736392022-09-13 15:24:34 +08009747 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009748 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009749 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009750 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009751
developer06a01d92022-09-07 16:32:39 +08009752 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009753 if (fp == NULL) {
9754 fprintf(stderr, "%s: popen failed\n", __func__);
9755 return RETURN_ERR;
9756 }
9757 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009758 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009759
developerce736392022-09-13 15:24:34 +08009760 if (strlen(str) == 0) // interface not exist
9761 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009762
developerce736392022-09-13 15:24:34 +08009763 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9764 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009765
developerce736392022-09-13 15:24:34 +08009766 memset(str, 0, sizeof(str));
9767 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009768 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009769 if (fp == NULL) {
9770 fprintf(stderr, "%s: popen failed\n", __func__);
9771 return RETURN_ERR;
9772 }
9773 fgets(str, sizeof(str), fp);
9774
9775 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9776 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009777 pclose(fp);
developerce736392022-09-13 15:24:34 +08009778
9779 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9780 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9781
9782 // Not supported
9783 output_struct->ssid_RetransCount = 0;
9784 output_struct->ssid_FailedRetransCount = 0;
9785 output_struct->ssid_RetryCount = 0;
9786 output_struct->ssid_MultipleRetryCount = 0;
9787 output_struct->ssid_ACKFailureCount = 0;
9788 output_struct->ssid_AggregatedPacketCount = 0;
9789
developer06a01d92022-09-07 16:32:39 +08009790 return RETURN_OK;
9791}
9792
9793//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).
9794INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9795{
9796 char output_val[16]={'\0'};
9797 char config_file[MAX_BUF_SIZE] = {0};
9798
9799 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9800 if (!output)
9801 return RETURN_ERR;
9802 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08009803 if (!syn_flag)
9804 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9805 else
developer07ded1f2024-01-10 10:30:15 +08009806 snprintf(output_val, sizeof(output_val), "%s", vap_info[apIndex].ap_isolate);
developer06a01d92022-09-07 16:32:39 +08009807 if( strcmp(output_val,"1") == 0 )
9808 *output = TRUE;
9809 else
9810 *output = FALSE;
9811 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9812
9813 return RETURN_OK;
9814}
9815
9816INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9817{
9818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9819 char str[MAX_BUF_SIZE]={'\0'};
9820 char string[MAX_BUF_SIZE]={'\0'};
9821 char cmd[MAX_CMD_SIZE]={'\0'};
9822 char *ch;
9823 char config_file[MAX_BUF_SIZE] = {0};
9824 struct params params;
9825
9826 if(enable == TRUE)
9827 strcpy(string,"1");
9828 else
9829 strcpy(string,"0");
9830
9831 params.name = "ap_isolate";
9832 params.value = string;
9833
9834 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9835 wifi_hostapdWrite(config_file,&params,1);
developerefb790a2023-12-26 18:58:32 +08009836 snprintf(vap_info[apIndex].ap_isolate, sizeof(vap_info[apIndex].ap_isolate), "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08009837 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9838
9839 return RETURN_OK;
9840}
9841
9842INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9843{
9844 if (NULL == output_dBm)
9845 return RETURN_ERR;
9846
9847 *output_dBm = 0;
9848 return RETURN_OK;
9849}
9850
9851INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9852{
9853 return RETURN_OK;
9854}
9855INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9856{
9857 return RETURN_OK;
9858}
9859INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9860{
9861 return RETURN_OK;
9862}
9863INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9864{
9865 return RETURN_OK;
9866}
9867INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9868{
9869 return RETURN_OK;
9870}
9871INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9872{
9873 char config_file[MAX_BUF_SIZE] = {0};
9874 struct params list;
9875
9876 list.name = "bss_transition";
9877 list.value = activate?"1":"0";
9878 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9879 wifi_hostapdWrite(config_file, &list, 1);
developerefb790a2023-12-26 18:58:32 +08009880 snprintf(vap_info[apIndex].bss_transition, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08009881
9882 return RETURN_OK;
9883}
9884wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9885
9886void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9887{
9888 return;
9889}
9890
9891INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9892{
9893 // TODO Implement me!
9894 return RETURN_OK;
9895}
9896
9897INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9898{
developera3c68b92022-09-13 15:27:29 +08009899 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009900 FILE *f = NULL;
9901
developer72ec5572023-01-05 16:27:13 +08009902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009903
developer72ec5572023-01-05 16:27:13 +08009904 if (essid == NULL)
9905 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009906
developer72ec5572023-01-05 16:27:13 +08009907 if (strlen(essid) == 0 || apIndex == -1) {
9908 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9909 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009910 }
9911
developer72ec5572023-01-05 16:27:13 +08009912 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9913 f = fopen(file_name, "w");
9914 if (f == NULL)
9915 return RETURN_ERR;
9916
9917 // For mode == 0 is to disable filter, just don't write ssid to the file.
9918 fprintf(f, "%d\n%s", mode, mode?essid:"");
9919 fclose(f);
9920 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009921 return RETURN_OK;
9922}
9923
9924INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9925{
9926 // TODO Implement me!
9927 //Apply wifi_pushRadioChannel() instantly
9928 return RETURN_ERR;
9929}
9930
9931INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9932{
9933 // TODO Implement me!
9934 return RETURN_OK;
9935}
9936
9937#ifdef HAL_NETLINK_IMPL
9938static int tidStats_callback(struct nl_msg *msg, void *arg) {
9939 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9940 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9941 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9942 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9943 int rem , tid_index = 0;
9944
9945 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9946 wifi_associated_dev_tid_entry_t *stats_entry;
9947
9948 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9949 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9950 };
9951 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9952 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9953 };
9954
9955 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9956 genlmsg_attrlen(gnlh, 0), NULL);
9957
9958
9959 if (!tb[NL80211_ATTR_STA_INFO]) {
9960 fprintf(stderr, "station stats missing!\n");
9961 return NL_SKIP;
9962 }
9963
9964 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9965 tb[NL80211_ATTR_STA_INFO],
9966 stats_policy)) {
9967 fprintf(stderr, "failed to parse nested attributes!\n");
9968 return NL_SKIP;
9969 }
9970
9971 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9972 {
9973 stats_entry = &out->tid_array[tid_index];
9974
9975 stats_entry->tid = tid_index;
9976 stats_entry->ac = _tid_ac_index_get[tid_index];
9977
9978 if(sinfo[NL80211_STA_INFO_TID_STATS])
9979 {
9980 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9981 printf("failed to parse nested stats attributes!");
9982 return NL_SKIP;
9983 }
9984 }
9985 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9986 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9987
9988 if(tid_index < (PS_MAX_TID - 1))
9989 tid_index++;
9990 }
9991 //ToDo: sum_time_ms, ewma_time_ms
9992 return NL_SKIP;
9993}
9994#endif
9995
9996INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9997{
9998#ifdef HAL_NETLINK_IMPL
9999 Netlink nl;
10000 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010001 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010002
developerac6f1142022-12-20 19:26:35 +080010003 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010004 return RETURN_ERR;
10005
10006 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010007
10008 nl.id = initSock80211(&nl);
10009
10010 if (nl.id < 0) {
10011 fprintf(stderr, "Error initializing netlink \n");
10012 return -1;
10013 }
10014
10015 struct nl_msg* msg = nlmsg_alloc();
10016
10017 if (!msg) {
10018 fprintf(stderr, "Failed to allocate netlink message.\n");
10019 nlfree(&nl);
10020 return -2;
10021 }
10022
10023 genlmsg_put(msg,
10024 NL_AUTO_PORT,
10025 NL_AUTO_SEQ,
10026 nl.id,
10027 0,
10028 0,
10029 NL80211_CMD_GET_STATION,
10030 0);
10031
10032 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10033 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10034 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
10035 nl_send_auto(nl.socket, msg);
10036 nl_recvmsgs(nl.socket, nl.cb);
10037 nlmsg_free(msg);
10038 nlfree(&nl);
10039 return RETURN_OK;
10040#else
10041//iw implementation
10042#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10043#define TOTAL_MAX_LINES 50
10044
10045 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +080010046 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +080010047 FILE *fp=NULL;
10048 char pipeCmd[1024]= {'\0'};
10049 int lines,tid_index=0;
10050 char mac_addr[20] = {'\0'};
10051
developerac6f1142022-12-20 19:26:35 +080010052 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010053 return RETURN_ERR;
10054
developer06a01d92022-09-07 16:32:39 +080010055 wifi_associated_dev_tid_entry_t *stats_entry;
10056
developer06a01d92022-09-07 16:32:39 +080010057 strcpy(mac_addr,clientMacAddress);
10058
10059 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10060 fp= popen(pipeCmd,"r");
10061 if(fp == NULL)
10062 {
10063 perror("popen for station dump failed\n");
10064 return RETURN_ERR;
10065 }
10066 pclose(fp);
10067
10068 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10069 fp=popen(pipeCmd,"r");
10070 if(fp == NULL)
10071 {
10072 perror("popen for grep station failed\n");
10073 return RETURN_ERR;
10074 }
10075 else if(fgets(buf,sizeof(buf),fp) != NULL)
10076 lines=atoi(buf);
10077 else
10078 {
10079 pclose(fp);
10080 fprintf(stderr,"No devices are connected \n");
10081 return RETURN_ERR;
10082 }
10083 pclose(fp);
10084
10085 if(lines == 1)
10086 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10087
10088 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10089 {
10090 stats_entry = &tid_stats->tid_array[tid_index];
10091 stats_entry->tid = tid_index;
10092
10093 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);
10094
10095 fp=popen(pipeCmd,"r");
10096 if(fp ==NULL)
10097 {
10098 perror("Failed to read from tid file \n");
10099 return RETURN_ERR;
10100 }
10101 else if(fgets(buf,sizeof(buf),fp) != NULL)
10102 stats_entry->num_msdus = atol(buf);
10103
10104 pclose(fp);
10105 stats_entry->ac = _tid_ac_index_get[tid_index];
10106// TODO:
10107// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10108// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10109 }
10110 return RETURN_OK;
10111#endif
10112}
10113
10114
10115INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10116{
developerd946fd62022-12-08 18:03:28 +080010117 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +080010118 char cmd[128]={0};
10119 char buf[128]={0};
10120 int freq = 0;
10121
10122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10123
10124 // full mode is used to scan all channels.
10125 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10126 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10127 ieee80211_channel_to_frequency(chan_list[0], &freq);
10128
developerac6f1142022-12-20 19:26:35 +080010129 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010130 return RETURN_ERR;
10131
developer615510b2022-09-27 10:14:35 +080010132 if (freq)
developerd946fd62022-12-08 18:03:28 +080010133 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +080010134 else
developerd946fd62022-12-08 18:03:28 +080010135 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +080010136
10137 _syscmd(cmd, buf, sizeof(buf));
10138 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10139
developer06a01d92022-09-07 16:32:39 +080010140 return RETURN_OK;
10141}
10142
10143
10144INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10145{
10146 // TODO Implement me!
10147 return RETURN_ERR;
10148}
10149
10150INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10151{
10152 // TODO Implement me!
10153 return RETURN_ERR;
10154}
10155
10156INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10157{
10158 // TODO Implement me!
10159 return RETURN_ERR;
10160}
10161
10162INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10163{
10164 // TODO Implement me!
10165 return RETURN_ERR;
10166}
10167
10168INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10169{
10170 // TODO Implement me!
10171 return RETURN_ERR;
10172}
10173
10174INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10175{
10176 // TODO Implement me!
10177 return RETURN_ERR;
10178}
10179
10180INT wifi_steering_eventUnregister(void)
10181{
10182 // TODO Implement me!
10183 return RETURN_ERR;
10184}
10185
10186INT wifi_delApAclDevices(INT apIndex)
10187{
10188#if 0
10189 char cmd[MAX_BUF_SIZE] = {0};
10190 char buf[MAX_BUF_SIZE] = {0};
10191
10192 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010193 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010194 if(_syscmd(cmd,buf,sizeof(buf)))
10195 return RETURN_ERR;
10196#endif
developer9988c232023-03-06 14:57:08 +080010197 char cmd[256]={0};
10198 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010199
developere6aafda2022-09-13 14:59:28 +080010200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010201 sprintf(cmd, "rm %s%d %s%d 2>&1 && touch %s%d %s%d", ACL_PREFIX, apIndex, DENY_PREFIX, apIndex, ACL_PREFIX, apIndex, DENY_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +080010202 if(_syscmd(cmd, buf, sizeof(buf)))
10203 return RETURN_ERR;
10204 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010205
10206 return RETURN_OK;
10207}
10208
10209#ifdef HAL_NETLINK_IMPL
10210static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10211 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10212 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10213 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10214 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10215 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10216 char mac_addr[20],dev[20];
10217
10218 nla_parse(tb,
10219 NL80211_ATTR_MAX,
10220 genlmsg_attrdata(gnlh, 0),
10221 genlmsg_attrlen(gnlh, 0),
10222 NULL);
10223
10224 if(!tb[NL80211_ATTR_STA_INFO]) {
10225 fprintf(stderr, "sta stats missing!\n");
10226 return NL_SKIP;
10227 }
10228
10229 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10230 fprintf(stderr, "failed to parse nested attributes!\n");
10231 return NL_SKIP;
10232 }
10233 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10234
10235 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10236
10237 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10238 fprintf(stderr, "failed to parse nested rate attributes!");
10239 return NL_SKIP;
10240 }
10241
10242 if(sinfo[NL80211_STA_INFO_TID_STATS])
10243 {
10244 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10245 printf("failed to parse nested stats attributes!");
10246 return NL_SKIP;
10247 }
10248 }
10249
10250 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10251 {
10252 printf("Type is VHT\n");
10253 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10254 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10255
10256 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10257 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10258 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10259 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10260 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10261 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10262 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10263 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10264 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10265 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10266 }
10267 else
10268 {
10269 printf(" OFDM or CCK \n");
10270 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10271 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10272 }
10273
10274 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10275 if(rinfo[NL80211_RATE_INFO_MCS])
10276 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10277 }
10278 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10279 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10280 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10281 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10282
10283 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10284 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10285
10286 if (sinfo[NL80211_STA_INFO_SIGNAL])
10287 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10288 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10289 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10290 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10291 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10292 //rssi_array need to be filled
10293 return NL_SKIP;
10294}
10295#endif
10296
10297INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10298{
10299#ifdef HAL_NETLINK_IMPL
10300 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010301 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010302 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010303 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010304
10305 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10306
10307 if (*output_array_size <= 0)
10308 return RETURN_OK;
10309
developer06a01d92022-09-07 16:32:39 +080010310 nl.id = initSock80211(&nl);
10311
10312 if (nl.id < 0) {
10313 fprintf(stderr, "Error initializing netlink \n");
10314 return 0;
10315 }
10316
10317 struct nl_msg* msg = nlmsg_alloc();
10318
10319 if (!msg) {
10320 fprintf(stderr, "Failed to allocate netlink message.\n");
10321 nlfree(&nl);
10322 return 0;
10323 }
10324
10325 genlmsg_put(msg,
10326 NL_AUTO_PORT,
10327 NL_AUTO_SEQ,
10328 nl.id,
10329 0,
10330 0,
10331 NL80211_CMD_GET_STATION,
10332 0);
10333
10334 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10335 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10336 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10337 nl_send_auto(nl.socket, msg);
10338 nl_recvmsgs(nl.socket, nl.cb);
10339 nlmsg_free(msg);
10340 nlfree(&nl);
10341 return RETURN_OK;
10342#else
10343 //TODO Implement me
10344 return RETURN_OK;
10345#endif
10346}
10347
10348#ifdef HAL_NETLINK_IMPL
10349static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10350 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10351 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10352 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10353 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10354 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10355 char mac_addr[20],dev[20];
10356
10357 nla_parse(tb,
10358 NL80211_ATTR_MAX,
10359 genlmsg_attrdata(gnlh, 0),
10360 genlmsg_attrlen(gnlh, 0),
10361 NULL);
10362
10363 if(!tb[NL80211_ATTR_STA_INFO]) {
10364 fprintf(stderr, "sta stats missing!\n");
10365 return NL_SKIP;
10366 }
10367
10368 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10369 fprintf(stderr, "failed to parse nested attributes!\n");
10370 return NL_SKIP;
10371 }
10372
10373 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10374
10375 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10376
10377 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10378 fprintf(stderr, "failed to parse nested rate attributes!");
10379 return NL_SKIP;
10380 }
10381
10382 if(sinfo[NL80211_STA_INFO_TID_STATS])
10383 {
10384 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10385 printf("failed to parse nested stats attributes!");
10386 return NL_SKIP;
10387 }
10388 }
10389 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10390 {
10391 printf("Type is VHT\n");
10392 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10393 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10394
10395 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10396 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10397 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10398 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10399 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10400 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10401 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10402 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10403 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10404 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10405 }
10406 else
10407 {
10408 printf(" OFDM or CCK \n");
10409 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10410 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10411 }
10412
10413 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10414 if(rinfo[NL80211_RATE_INFO_MCS])
10415 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10416 }
10417
10418 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10419 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10420 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10421 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10422
10423 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10424 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10425 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10426
10427 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10428 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10429
10430 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10431 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10432
10433 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10434 ((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]);
10435
10436 return NL_SKIP;
10437}
10438#endif
10439
10440INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10441{
10442#ifdef HAL_NETLINK_IMPL
10443 Netlink nl;
10444 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010445 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010446 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010447 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010448
10449 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10450
10451 if (*output_array_size <= 0)
10452 return RETURN_OK;
10453
developerd946fd62022-12-08 18:03:28 +080010454 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010455
10456 nl.id = initSock80211(&nl);
10457
10458 if(nl.id < 0) {
10459 fprintf(stderr, "Error initializing netlink \n");
10460 return 0;
10461 }
10462
10463 struct nl_msg* msg = nlmsg_alloc();
10464
10465 if(!msg) {
10466 fprintf(stderr, "Failed to allocate netlink message.\n");
10467 nlfree(&nl);
10468 return 0;
10469 }
10470
10471 genlmsg_put(msg,
10472 NL_AUTO_PORT,
10473 NL_AUTO_SEQ,
10474 nl.id,
10475 0,
10476 0,
10477 NL80211_CMD_GET_STATION,
10478 0);
10479
10480 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10481 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10482 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10483 nl_send_auto(nl.socket, msg);
10484 nl_recvmsgs(nl.socket, nl.cb);
10485 nlmsg_free(msg);
10486 nlfree(&nl);
10487 return RETURN_OK;
10488#else
10489 //TODO Implement me
10490 return RETURN_OK;
10491#endif
10492}
10493
10494INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10495{
10496 // TODO Implement me!
10497 char buf[MAX_BUF_SIZE] = {0};
10498 char config_file[MAX_BUF_SIZE] = {0};
10499
10500 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +080010501 if (!syn_flag)
10502 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10503 else
developer07ded1f2024-01-10 10:30:15 +080010504 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].bss_transition);
developer06a01d92022-09-07 16:32:39 +080010505 *activate = (strncmp("1",buf,1) == 0);
10506
10507 return RETURN_OK;
10508}
10509
10510INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10511{
10512 char config_file[MAX_BUF_SIZE] = {0};
10513 struct params list;
10514
10515 list.name = "rrm_neighbor_report";
10516 list.value = activate?"1":"0";
10517 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10518 wifi_hostapdWrite(config_file, &list, 1);
10519
10520 return RETURN_OK;
10521}
10522
10523INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10524{
10525 char buf[32] = {0};
10526 char config_file[MAX_BUF_SIZE] = {0};
10527
10528 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10529 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10530 *activate = (strncmp("1",buf,1) == 0);
10531
10532 return RETURN_OK;
10533}
10534#undef HAL_NETLINK_IMPL
10535#ifdef HAL_NETLINK_IMPL
10536static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10537 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10538 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10539 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10540 char dev[20];
10541 int freq =0 ;
10542 static int i=0;
10543
10544 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10545
10546 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10547 };
10548
10549 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10550
10551 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10552
10553 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10554 fprintf(stderr, "survey data missing!\n");
10555 return NL_SKIP;
10556 }
10557
10558 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10559 {
10560 fprintf(stderr, "failed to parse nested attributes!\n");
10561 return NL_SKIP;
10562 }
10563
10564
10565 if(out[0].array_size == 1 )
10566 {
10567 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10568 {
10569 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10570 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10571 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10572
10573 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10574 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10575 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10576 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10577 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10578 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10579 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10580 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10581 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10582 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10583 if (sinfo[NL80211_SURVEY_INFO_TIME])
10584 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10585 return NL_STOP;
10586 }
10587 }
10588 else
10589 {
10590 if ( i <= out[0].array_size )
10591 {
10592 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10593 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10594 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10595
10596 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10597 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10598 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10599 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10600 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10601 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10602 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10603 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10604 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10605 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10606 if (sinfo[NL80211_SURVEY_INFO_TIME])
10607 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10608 }
10609 }
10610
10611 i++;
10612 return NL_SKIP;
10613}
10614#endif
10615
10616static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10617{
10618 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10619 FILE *fp;
10620
10621 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10622 {
10623 printf("Creating Frequency-Channel Map\n");
10624 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10625 }
10626 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10627 if((fp = popen(command, "r")))
10628 {
10629 fgets(output, sizeof(output), fp);
10630 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010631 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010632 }
10633
10634 return 0;
10635}
10636
10637static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10638{
10639 int freqMHz = -1;
10640 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010641 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010642
10643 ieee80211_channel_to_frequency(channel, &freqMHz);
10644 if (freqMHz == -1) {
10645 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10646 return -1;
10647 }
10648
developer7930d352022-12-21 17:55:42 +080010649 wifi_GetInterfaceName(radioIndex, interface_name);
10650 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010651 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10652 radioIndex, freqMHz);
10653 return -1;
10654 }
10655
10656 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10657 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10658 return -1;
10659 }
10660
10661 return 0;
10662}
10663
10664static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10665{
10666 const char *ptr = buf;
10667 char *key = NULL;
10668 char *val = NULL;
10669 char line[256] = { '\0' };
10670
10671 while (ptr = get_line_from_str_buf(ptr, line)) {
10672 if (strstr(line, "Frequency")) continue;
10673
10674 key = strtok(line, ":");
10675 val = strtok(NULL, " ");
10676 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10677
10678 if (!strcmp(key, "noise")) {
10679 sscanf(val, "%d", &stats->ch_noise);
10680 if (stats->ch_noise == 0) {
10681 // Workaround for missing noise information.
10682 // Assume -95 for 2.4G and -103 for 5G
10683 if (radioIndex == 0) stats->ch_noise = -95;
10684 if (radioIndex == 1) stats->ch_noise = -103;
10685 }
10686 }
10687 else if (!strcmp(key, "channel active time")) {
10688 sscanf(val, "%llu", &stats->ch_utilization_total);
10689 }
10690 else if (!strcmp(key, "channel busy time")) {
10691 sscanf(val, "%llu", &stats->ch_utilization_busy);
10692 }
10693 else if (!strcmp(key, "channel receive time")) {
10694 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10695 }
10696 else if (!strcmp(key, "channel transmit time")) {
10697 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10698 }
10699 };
10700
10701 return 0;
10702}
10703
10704INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10705{
10706 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10707#ifdef HAL_NETLINK_IMPL
10708 Netlink nl;
10709 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010710 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010711
10712 local[0].array_size = array_size;
10713
developerac6f1142022-12-20 19:26:35 +080010714 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010715 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010716
10717 nl.id = initSock80211(&nl);
10718
10719 if (nl.id < 0) {
10720 fprintf(stderr, "Error initializing netlink \n");
10721 return -1;
10722 }
10723
10724 struct nl_msg* msg = nlmsg_alloc();
10725
10726 if (!msg) {
10727 fprintf(stderr, "Failed to allocate netlink message.\n");
10728 nlfree(&nl);
10729 return -2;
10730 }
10731
10732 genlmsg_put(msg,
10733 NL_AUTO_PORT,
10734 NL_AUTO_SEQ,
10735 nl.id,
10736 0,
10737 NLM_F_DUMP,
10738 NL80211_CMD_GET_SURVEY,
10739 0);
10740
10741 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10742 nl_send_auto(nl.socket, msg);
10743 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10744 nl_recvmsgs(nl.socket, nl.cb);
10745 nlmsg_free(msg);
10746 nlfree(&nl);
10747 //Copying the Values
10748 for(int i=0;i<array_size;i++)
10749 {
10750 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10751 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10752 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10753 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10754 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10755 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10756 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10757 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10758 }
10759#else
10760 ULONG channel = 0;
10761 int i;
10762 int number_of_channels = array_size;
10763 char buf[512];
10764 INT ret;
10765 wifi_channelStats_t tmp_stats;
10766
10767 if (number_of_channels == 0) {
10768 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10769 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10770 return RETURN_ERR;
10771 }
10772 number_of_channels = 1;
10773 input_output_channelStats_array[0].ch_number = channel;
10774 }
10775
10776 for (i = 0; i < number_of_channels; i++) {
10777
10778 input_output_channelStats_array[i].ch_noise = 0;
10779 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10780 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10781 input_output_channelStats_array[i].ch_utilization_busy = 0;
10782 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10783 input_output_channelStats_array[i].ch_utilization_total = 0;
10784
10785 memset(buf, 0, sizeof(buf));
10786 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10787 return RETURN_ERR;
10788 }
10789 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10790 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10791 return RETURN_ERR;
10792 }
10793
10794 // XXX: fake missing 'self' counter which is not available in iw survey output
10795 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10796 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10797
10798 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10799 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10800 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10801 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10802 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10803
10804 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",
10805 __func__,
10806 input_output_channelStats_array[i].ch_number,
10807 input_output_channelStats_array[i].ch_noise,
10808 input_output_channelStats_array[i].ch_utilization_total,
10809 input_output_channelStats_array[i].ch_utilization_busy,
10810 input_output_channelStats_array[i].ch_utilization_busy_rx,
10811 input_output_channelStats_array[i].ch_utilization_busy_tx,
10812 input_output_channelStats_array[i].ch_utilization_busy_self,
10813 input_output_channelStats_array[i].ch_utilization_busy_ext);
10814 }
10815#endif
10816 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10817 return RETURN_OK;
10818}
10819#define HAL_NETLINK_IMPL
10820
10821/* Hostapd events */
10822
10823#ifndef container_of
10824#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10825#define container_of(ptr, type, member) \
10826 ((type *)((char *)ptr - offset_of(type, member)))
10827#endif /* container_of */
10828
10829struct ctrl {
10830 char sockpath[128];
10831 char sockdir[128];
10832 char bss[IFNAMSIZ];
10833 char reply[4096];
10834 int ssid_index;
10835 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10836 void (*overrun)(struct ctrl *ctrl);
10837 struct wpa_ctrl *wpa;
10838 unsigned int ovfl;
10839 size_t reply_len;
10840 int initialized;
10841 ev_timer retry;
10842 ev_timer watchdog;
10843 ev_stat stat;
10844 ev_io io;
10845};
10846static wifi_newApAssociatedDevice_callback clients_connect_cb;
10847static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10848static struct ctrl wpa_ctrl[MAX_APS];
10849static int initialized;
10850
10851static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10852{
10853 char cbuf[256] = {};
10854 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10855 struct cmsghdr *cmsg;
10856 unsigned int ovfl = ctrl->ovfl;
10857 unsigned int drop;
10858
10859 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10860 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10861 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10862 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10863
10864 drop = ovfl - ctrl->ovfl;
10865 ctrl->ovfl = ovfl;
10866
10867 return drop;
10868}
10869
10870static void ctrl_close(struct ctrl *ctrl)
10871{
10872 if (ctrl->io.cb)
10873 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10874 if (ctrl->retry.cb)
10875 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10876 if (!ctrl->wpa)
10877 return;
10878
10879 wpa_ctrl_detach(ctrl->wpa);
10880 wpa_ctrl_close(ctrl->wpa);
10881 ctrl->wpa = NULL;
10882 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10883}
10884
10885static void ctrl_process(struct ctrl *ctrl)
10886{
10887 const char *str;
10888 int drops;
10889 int level;
10890 int err;
10891
10892 /* Example events:
10893 *
10894 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10895 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10896 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10897 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10898 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10899 */
10900 if (!(str = index(ctrl->reply, '>')))
10901 return;
10902 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10903 return;
10904
10905 str++;
10906
10907 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10908 if (!(str = index(ctrl->reply, ' ')))
10909 return;
10910 wifi_associated_dev_t sta;
10911 memset(&sta, 0, sizeof(sta));
10912
10913 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10914 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10915 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10916
10917 sta.cli_Active=true;
10918
10919 (clients_connect_cb)(ctrl->ssid_index, &sta);
10920 goto handled;
10921 }
10922
10923 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10924 if (!(str = index(ctrl->reply, ' ')))
10925 return;
10926
10927 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10928 goto handled;
10929 }
10930
10931 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10932 printf("CTRL_WPA: handle TERMINATING event\n");
10933 goto retry;
10934 }
10935
10936 if (strncmp("AP-DISABLED", str, 11) == 0) {
10937 printf("CTRL_WPA: handle AP-DISABLED\n");
10938 goto retry;
10939 }
10940
10941 printf("Event not supported!!\n");
10942
10943handled:
10944
10945 if ((drops = ctrl_get_drops(ctrl))) {
10946 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10947 if (ctrl->overrun)
10948 ctrl->overrun(ctrl);
10949 }
10950
10951 return;
10952
10953retry:
10954 printf("WPA_CTRL: closing\n");
10955 ctrl_close(ctrl);
10956 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10957 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10958}
10959
10960static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10961{
10962 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10963 int err;
10964
10965 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10966 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10967 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10968 ctrl->reply[ctrl->reply_len] = 0;
10969 if (err < 0) {
10970 if (errno == EAGAIN || errno == EWOULDBLOCK)
10971 return;
10972 ctrl_close(ctrl);
10973 ev_timer_again(EV_A_ &ctrl->retry);
10974 return;
10975 }
10976
10977 ctrl_process(ctrl);
10978}
10979
10980static int ctrl_open(struct ctrl *ctrl)
10981{
10982 int fd;
10983
10984 if (ctrl->wpa)
10985 return 0;
10986
10987 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10988 if (!ctrl->wpa)
10989 goto err;
10990
10991 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10992 goto err_close;
10993
10994 fd = wpa_ctrl_get_fd(ctrl->wpa);
10995 if (fd < 0)
10996 goto err_detach;
10997
10998 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10999 goto err_detach;
11000
11001 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11002 ev_io_start(EV_DEFAULT_ &ctrl->io);
11003
11004 return 0;
11005
11006err_detach:
11007 wpa_ctrl_detach(ctrl->wpa);
11008err_close:
11009 wpa_ctrl_close(ctrl->wpa);
11010err:
11011 ctrl->wpa = NULL;
11012 return -1;
11013}
11014
11015static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11016{
11017 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11018
11019 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11020 ctrl_open(ctrl);
11021}
11022
11023static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11024{
11025 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11026
11027 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11028 if (ctrl_open(ctrl) == 0) {
11029 printf("WPA_CTRL: retry successful\n");
11030 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11031 }
11032}
11033
11034int ctrl_enable(struct ctrl *ctrl)
11035{
11036 if (ctrl->wpa)
11037 return 0;
11038
11039 if (!ctrl->stat.cb) {
11040 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11041 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11042 }
11043
11044 if (!ctrl->retry.cb) {
11045 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11046 }
11047
11048 return ctrl_open(ctrl);
11049}
11050
11051static void
11052ctrl_msg_cb(char *buf, size_t len)
11053{
11054 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11055
11056 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11057 ctrl_process(ctrl);
11058}
11059
11060static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11061{
11062 int err;
11063
11064 if (!ctrl->wpa)
11065 return -1;
11066 if (*reply_len < 2)
11067 return -1;
11068
11069 (*reply_len)--;
11070 ctrl->reply_len = sizeof(ctrl->reply);
11071 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11072 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11073 if (err < 0)
11074 return err;
11075
11076 if (ctrl->reply_len > *reply_len)
11077 ctrl->reply_len = *reply_len;
11078
11079 *reply_len = ctrl->reply_len;
11080 memcpy(reply, ctrl->reply, *reply_len);
11081 reply[*reply_len - 1] = 0;
11082 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11083 return 0;
11084}
11085
11086static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11087{
11088 const char *pong = "PONG";
11089 const char *ping = "PING";
11090 char reply[1024];
11091 size_t len = sizeof(reply);
11092 int err;
11093 ULONG s, snum;
11094 INT ret;
11095 BOOL status;
11096
11097 printf("WPA_CTRL: watchdog cb\n");
11098
11099 ret = wifi_getSSIDNumberOfEntries(&snum);
11100 if (ret != RETURN_OK) {
11101 printf("%s: failed to get SSID count", __func__);
11102 return;
11103 }
11104
11105 if (snum > MAX_APS) {
11106 printf("more ssid than supported! %lu\n", snum);
11107 return;
11108 }
11109
11110 for (s = 0; s < snum; s++) {
11111 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080011112 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080011113 continue;
11114 }
11115 if (status == false) continue;
11116
11117 memset(reply, 0, sizeof(reply));
11118 len = sizeof(reply);
11119 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11120 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11121 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11122 continue;
11123
11124 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11125 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080011126 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080011127 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11128 }
11129}
11130
11131static int init_wpa()
11132{
11133 int ret = 0, i = 0;
11134 ULONG s, snum;
11135
11136 ret = wifi_getSSIDNumberOfEntries(&snum);
11137 if (ret != RETURN_OK) {
11138 printf("%s: failed to get SSID count", __func__);
11139 return RETURN_ERR;
11140 }
11141
11142 if (snum > MAX_APS) {
11143 printf("more ssid than supported! %lu\n", snum);
11144 return RETURN_ERR;
11145 }
11146
11147 for (s = 0; s < snum; s++) {
11148 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11149 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11150 wpa_ctrl[s].ssid_index = s;
11151 ctrl_enable(&wpa_ctrl[s]);
11152 }
11153
11154 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11155 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11156
11157 initialized = 1;
11158 printf("WPA_CTRL: initialized\n");
11159
11160 return RETURN_OK;
11161}
11162
11163void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11164{
11165 clients_connect_cb = callback_proc;
11166 if (!initialized)
11167 init_wpa();
11168}
11169
11170void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11171{
11172 clients_disconnect_cb = callback_proc;
11173 if (!initialized)
11174 init_wpa();
11175}
11176
11177INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11178{
11179 // TODO Implement me!
11180 return RETURN_ERR;
11181}
11182
11183INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11184{
11185 // TODO Implement me!
11186 return RETURN_ERR;
11187}
11188
11189INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11190{
11191 int i;
developer4b102122023-02-15 10:53:03 +080011192 int phyId = -1;
11193 char cmd[256] = {0};
11194 char channel_numbers_buf[256] = {0};
11195 char dfs_state_buf[256] = {0};
11196 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011197 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011198 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080011199
developer4b102122023-02-15 10:53:03 +080011200 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011201
developer4b102122023-02-15 10:53:03 +080011202 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11203 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011204
developer4b102122023-02-15 10:53:03 +080011205 snprintf(cmd, sizeof (cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v '%sno IR\\|5340\\|5480' | awk '{print $4}' | tr -d '[]'", phyId, dfs_enable?"":"radar\\|");
developer06a01d92022-09-07 16:32:39 +080011206
developer4b102122023-02-15 10:53:03 +080011207 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11208 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11209 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011210 }
11211
developer4b102122023-02-15 10:53:03 +080011212 ptr = channel_numbers_buf;
11213 i = 0;
11214 while (ptr = get_line_from_str_buf(ptr, line)) {
11215 if (i >= outputMapSize) {
11216 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11217 return RETURN_ERR;
11218 }
11219 sscanf(line, "%d", &outputMap[i].ch_number);
11220
11221 memset(cmd, 0, sizeof(cmd));
11222 // Below command should fetch string for DFS state (usable, available or unavailable)
11223 // Example line: "DFS state: usable (for 78930 sec)"
11224 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) {
11225 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011226 return RETURN_ERR;
11227 }
11228
developer4b102122023-02-15 10:53:03 +080011229 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11230 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011231 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11232 return RETURN_ERR;
11233 }
11234
developer4b102122023-02-15 10:53:03 +080011235 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011236
developer4b102122023-02-15 10:53:03 +080011237 if (!strcmp(dfs_state_buf, "usable")) {
11238 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11239 } else if (!strcmp(dfs_state_buf, "available")) {
11240 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11241 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11242 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11243 } else {
11244 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011245 }
developer4b102122023-02-15 10:53:03 +080011246 i++;
developer06a01d92022-09-07 16:32:39 +080011247 }
11248
developer4b102122023-02-15 10:53:03 +080011249 return RETURN_OK;
11250
developer06a01d92022-09-07 16:32:39 +080011251 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11252 return RETURN_ERR;
11253}
11254
11255INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11256{
11257 // TODO Implement me!
11258 return RETURN_ERR;
11259}
11260
11261INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11262{
11263 return RETURN_OK;
11264}
11265
11266INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11267{
11268 // TODO Implement me!
11269 return RETURN_ERR;
11270}
11271
11272INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11273{
11274 // TODO API refrence Implementaion is present on RPI hal
11275 return RETURN_ERR;
11276}
11277
developerfeab1d12023-09-27 11:29:38 +080011278
developer06a01d92022-09-07 16:32:39 +080011279INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11280{
developera5005b62022-09-13 15:43:35 +080011281 char cmd[128]={'\0'};
11282 char buf[128]={'\0'};
developerfeab1d12023-09-27 11:29:38 +080011283 int radioIndex = -1;
11284 int phyIndex = -1;
11285 bool enabled = false;
11286 int cur_tx_dbm = 0;
developera5005b62022-09-13 15:43:35 +080011287
11288 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfeab1d12023-09-27 11:29:38 +080011289
developera5005b62022-09-13 15:43:35 +080011290 if(txpwr_pcntg == NULL)
11291 return RETURN_ERR;
11292
developerfeab1d12023-09-27 11:29:38 +080011293 // The API name as getRadioXXX, I think the input index should be radioIndex,
11294 // but current we not change the name, but use it as radioIndex
11295 radioIndex = apIndex;
11296 phyIndex = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +080011297
developera5005b62022-09-13 15:43:35 +080011298 // Get the maximum tx power of the device
developerfeab1d12023-09-27 11:29:38 +080011299 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +080011300 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developera5005b62022-09-13 15:43:35 +080011301 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011302 if (strcmp(buf, "enable") == 0)
11303 enabled = true;
developera5005b62022-09-13 15:43:35 +080011304
developerfeab1d12023-09-27 11:29:38 +080011305 if (!enabled) {
11306 *txpwr_pcntg = 100;
11307 return RETURN_OK;
11308 }
11309
developera5005b62022-09-13 15:43:35 +080011310 memset(cmd, 0, sizeof(cmd));
11311 memset(buf, 0, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011312 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +080011313 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developera5005b62022-09-13 15:43:35 +080011314 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011315 cur_tx_dbm = strtol(buf, NULL, 10);
developera5005b62022-09-13 15:43:35 +080011316
developerfeab1d12023-09-27 11:29:38 +080011317 switch (cur_tx_dbm) {
11318 case 0:
11319 *txpwr_pcntg = 100; // range 91-100
developera5005b62022-09-13 15:43:35 +080011320 break;
developerfeab1d12023-09-27 11:29:38 +080011321 case 1:
11322 *txpwr_pcntg = 75; // range 61-90
11323 break;
11324 case 3:
11325 *txpwr_pcntg = 50; // range 31-60
11326 break;
11327 case 6:
11328 *txpwr_pcntg = 25; // range 16-30
11329 break;
11330 case 9:
11331 *txpwr_pcntg = 12; // range 10-15
11332 break;
11333 case 12:
11334 *txpwr_pcntg = 6; // range 1-9
11335 break;
11336 default:
11337 *txpwr_pcntg = 100; // 0
developera5005b62022-09-13 15:43:35 +080011338 }
developerfeab1d12023-09-27 11:29:38 +080011339
developer06a01d92022-09-07 16:32:39 +080011340 return RETURN_OK;
11341}
11342
11343INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11344{
developer58599c22022-09-13 16:40:34 +080011345 // TODO precac feature.
11346 struct params params = {0};
11347 char config_file[128] = {0};
11348
11349 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11350
11351 params.name = "enable_background_radar";
11352 params.value = enable?"1":"0";
11353 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11354 wifi_hostapdWrite(config_file, &params, 1);
11355 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11356
11357 /* TODO precac feature */
11358
11359 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11360 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011361}
11362
11363INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11364{
developer58599c22022-09-13 16:40:34 +080011365 char config_file[128] = {0};
11366 char buf[64] = {0};
11367
11368 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11369 if (NULL == enable || NULL == precac)
11370 return RETURN_ERR;
11371
11372 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11373 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011374 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011375 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011376 *precac = true;
11377 } else {
developer58599c22022-09-13 16:40:34 +080011378 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011379 *precac = false;
11380 }
developer58599c22022-09-13 16:40:34 +080011381
11382 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11383 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011384}
11385
11386INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11387{
developer58599c22022-09-13 16:40:34 +080011388 *supported = TRUE;
11389 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011390}
11391
developera7149722023-01-11 11:36:21 +080011392bool check_is_hemu_vendor_new_patch() {
11393 char cmd[128] = {0};
11394 char buf[128] = {0};
11395
11396 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11397 _syscmd(cmd, buf, sizeof(buf));
11398
11399 if (strlen(buf) > 0)
11400 return FALSE;
11401 else
11402 return TRUE;
11403}
11404
developer3e6b1692022-09-30 18:04:05 +080011405INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11406{
11407 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11408 struct params params = {0};
11409 char config_file[64] = {0};
11410 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011411 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011412 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011413 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11415
developera7149722023-01-11 11:36:21 +080011416 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011417
11418 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11419 set_mu_type &= ~0x05; // unset bit 0, 2
11420 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11421 set_mu_type |= 0x01;
11422 set_mu_type &= ~0x04;
11423 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11424 set_mu_type &= ~0x01;
11425 set_mu_type |= 0x04;
11426 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11427 set_mu_type |= 0x05; // set bit 0, 2
11428 }
11429
developera7149722023-01-11 11:36:21 +080011430 new_vendor_patch = check_is_hemu_vendor_new_patch();
11431 if (new_vendor_patch)
11432 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11433 else
11434 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11435
11436 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011437 sprintf(buf, "%u", set_mu_type);
11438 params.value = buf;
11439 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11440 wifi_hostapdWrite(config_file, &params, 1);
11441 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011442 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011443
11444 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11445 return RETURN_OK;
11446}
11447
11448INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11449{
11450 struct params params={0};
11451 char config_file[64] = {0};
11452 char buf[64] = {0};
11453 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011454 bool new_vendor_patch = FALSE;
11455 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011456
11457 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11458
11459 if (mu_type == NULL)
11460 return RETURN_ERR;
11461
developera7149722023-01-11 11:36:21 +080011462 new_vendor_patch = check_is_hemu_vendor_new_patch();
11463
11464 if (new_vendor_patch)
11465 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11466 else
11467 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11468
developer3e6b1692022-09-30 18:04:05 +080011469 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011470 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011471 get_mu_type = strtol(buf, NULL, 10);
11472
11473 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11474 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11475 else if (get_mu_type & 0x04)
11476 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11477 else if (get_mu_type & 0x01)
11478 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11479 else
11480 *mu_type = WIFI_DL_MU_TYPE_NONE;
11481
11482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11483 return RETURN_OK;
11484}
11485
11486INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11487{
11488 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11489 struct params params={0};
11490 char config_file[64] = {0};
11491 char buf[64] = {0};
11492 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011493 bool new_vendor_patch = FALSE;
11494 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11496
developera7149722023-01-11 11:36:21 +080011497 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011498
11499 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11500 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11501 set_mu_type &= ~0x0a;
11502 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11503 set_mu_type |= 0x02;
11504 set_mu_type &= ~0x08;
11505 }
11506
developera7149722023-01-11 11:36:21 +080011507 new_vendor_patch = check_is_hemu_vendor_new_patch();
11508
11509 if (new_vendor_patch)
11510 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11511 else
11512 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11513
11514 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011515 sprintf(buf, "%u", set_mu_type);
11516 params.value = buf;
11517 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11518 wifi_hostapdWrite(config_file, &params, 1);
11519 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011520 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011521
11522 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11523 return RETURN_OK;
11524}
11525
11526INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11527{
11528 struct params params={0};
11529 char config_file[64] = {0};
11530 char buf[64] = {0};
11531 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011532 bool new_vendor_patch = FALSE;
11533 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011534
11535 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11536
developera7149722023-01-11 11:36:21 +080011537 new_vendor_patch = check_is_hemu_vendor_new_patch();
11538
11539 if (new_vendor_patch)
11540 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11541 else
11542 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11543
developer3e6b1692022-09-30 18:04:05 +080011544 if (mu_type == NULL)
11545 return RETURN_ERR;
11546
11547 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011548 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011549
11550 get_mu_type = strtol(buf, NULL, 10);
11551 if (get_mu_type & 0x02)
11552 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11553 else
11554 *mu_type = WIFI_DL_MU_TYPE_NONE;
11555
11556 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11557 return RETURN_OK;
11558}
11559
11560
developer454b9462022-09-13 15:29:16 +080011561INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11562{
11563 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011564 char buf[256] = {0};
11565 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011566 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011567 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011568 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011569 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011570
11571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11572
developer254882b2022-09-30 17:12:31 +080011573 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011574 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11575 return RETURN_ERR;
11576 }
developer454b9462022-09-13 15:29:16 +080011577
developer254882b2022-09-30 17:12:31 +080011578 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011579 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011580
developer254882b2022-09-30 17:12:31 +080011581 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11582 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011583 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011584 _syscmd(cmd, buf, sizeof(buf));
11585 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11586 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11587 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011588 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011589 _syscmd(cmd, buf, sizeof(buf));
11590 }
11591 if (band == band_5) {
11592 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11593 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011594 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011595 _syscmd(cmd, buf, sizeof(buf));
11596 }
11597 }
11598 }
11599 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011600
developer254882b2022-09-30 17:12:31 +080011601 if (guard_interval == wifi_guard_interval_400)
11602 strcpy(GI, "0.4");
11603 else if (guard_interval == wifi_guard_interval_800)
11604 strcpy(GI, "0.8");
11605 else if (guard_interval == wifi_guard_interval_1600)
11606 strcpy(GI, "1.6");
11607 else if (guard_interval == wifi_guard_interval_3200)
11608 strcpy(GI, "3.2");
11609 else if (guard_interval == wifi_guard_interval_auto)
11610 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011611 // Record GI for get GI function
11612 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11613 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011614 if (f == NULL)
11615 return RETURN_ERR;
11616 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011617 fclose(f);
11618 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11619 return RETURN_OK;
11620}
11621
11622INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11623{
11624 char buf[32] = {0};
11625 char cmd[64] = {0};
11626
11627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11628
11629 if (guard_interval == NULL)
11630 return RETURN_ERR;
11631
developer7c4cd202023-03-01 10:56:29 +080011632 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011633 _syscmd(cmd, buf, sizeof(buf));
11634
11635 if (strncmp(buf, "0.4", 3) == 0)
11636 *guard_interval = wifi_guard_interval_400;
11637 else if (strncmp(buf, "0.8", 3) == 0)
11638 *guard_interval = wifi_guard_interval_800;
11639 else if (strncmp(buf, "1.6", 3) == 0)
11640 *guard_interval = wifi_guard_interval_1600;
11641 else if (strncmp(buf, "3.2", 3) == 0)
11642 *guard_interval = wifi_guard_interval_3200;
11643 else
11644 *guard_interval = wifi_guard_interval_auto;
11645
11646 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11647 return RETURN_OK;
11648}
11649
developer3cc61d12022-09-13 16:36:05 +080011650INT wifi_setBSSColor(INT radio_index, UCHAR color)
11651{
11652 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11653 struct params params = {0};
11654 char config_file[128] = {0};
11655 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011656 UCHAR *color_list;
11657 int color_num = 0;
11658 int maxNumberColors = 64;
11659 BOOL color_is_aval = FALSE;
11660
developerbf0b9dc2023-07-06 14:30:54 +080011661 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011662 return RETURN_ERR;
11663
developer517f3be2023-05-08 10:02:39 +080011664 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11665 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11666 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011667 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011668 }
developer2acb9632023-03-14 14:58:31 +080011669
11670 for (int i = 0; i < color_num; i++) {
11671 if (color_list[i] == color) {
11672 color_is_aval = TRUE;
11673 break;
11674 }
11675 }
11676 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011677 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011678 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11679 return RETURN_ERR;
11680 }
developer3cc61d12022-09-13 16:36:05 +080011681
11682 params.name = "he_bss_color";
11683 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11684 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011685 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011686 wifi_hostapdWrite(config_file, &params, 1);
11687 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011688 wifi_reloadAp(radio_index);
11689
developer517f3be2023-05-08 10:02:39 +080011690 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11692 return RETURN_OK;
11693}
11694
11695INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11696{
developer3cc61d12022-09-13 16:36:05 +080011697 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011698 char cmd[128] = {0};
11699 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011700
developer3cc61d12022-09-13 16:36:05 +080011701 if (NULL == color)
11702 return RETURN_ERR;
11703
developer2acb9632023-03-14 14:58:31 +080011704 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11705 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011706
developer2acb9632023-03-14 14:58:31 +080011707 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11708 _syscmd(cmd, buf, sizeof(buf));
11709 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011710
developer2acb9632023-03-14 14:58:31 +080011711 return RETURN_OK;
11712}
11713
11714INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11715{
11716 char buf[64] = {0};
11717 char cmd[128] = {0};
11718 char interface_name[16] = {0};
11719 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011720
developer2acb9632023-03-14 14:58:31 +080011721 if (NULL == colorList || NULL == numColorReturned)
11722 return RETURN_ERR;
11723
11724 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11725 return RETURN_ERR;
11726
11727 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11728 _syscmd(cmd, buf, sizeof(buf));
11729 color_bitmap = strtoull(buf, NULL, 16);
11730
11731 *numColorReturned = 0;
11732 for (int i = 0; i < maxNumberColors; i++) {
11733 if (color_bitmap & 1) {
11734 colorList[*numColorReturned] = i;
11735 (*numColorReturned) += 1;
11736 }
11737 color_bitmap >>= 1;
11738 }
developer3cc61d12022-09-13 16:36:05 +080011739 return RETURN_OK;
11740}
11741
developer06a01d92022-09-07 16:32:39 +080011742/* multi-psk support */
11743INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11744{
11745 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011746 char interface_name[16] = {0};
11747
developerac6f1142022-12-20 19:26:35 +080011748 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011749 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011750
developerd946fd62022-12-08 18:03:28 +080011751 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11752 interface_name,
developer06a01d92022-09-07 16:32:39 +080011753 mac[0],
11754 mac[1],
11755 mac[2],
11756 mac[3],
11757 mac[4],
11758 mac[5]
11759 );
11760 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11761 _syscmd(cmd, key->wifi_keyId, 64);
11762
11763
11764 return RETURN_OK;
11765}
11766
11767INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11768{
developerd946fd62022-12-08 18:03:28 +080011769 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011770 FILE *fd = NULL;
11771 char fname[100];
11772 char cmd[128] = {0};
11773 char out[64] = {0};
11774 wifi_key_multi_psk_t * key = NULL;
11775 if(keysNumber < 0)
11776 return RETURN_ERR;
11777
developer431128d2022-12-16 15:30:41 +080011778 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011779 fd = fopen(fname, "w");
11780 if (!fd) {
11781 return RETURN_ERR;
11782 }
11783 key= (wifi_key_multi_psk_t *) keys;
11784 for(int i=0; i<keysNumber; ++i, key++) {
11785 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11786 }
11787 fclose(fd);
11788
11789 //reload file
developerac6f1142022-12-20 19:26:35 +080011790 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011791 return RETURN_ERR;
11792 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011793 _syscmd(cmd, out, 64);
11794 return RETURN_OK;
11795}
11796
11797INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11798{
11799 FILE *fd = NULL;
11800 char fname[100];
11801 char * line = NULL;
11802 char * pos = NULL;
11803 size_t len = 0;
11804 ssize_t read = 0;
11805 INT ret = RETURN_OK;
11806 wifi_key_multi_psk_t *keys_it = NULL;
11807
11808 if (keysNumber < 1) {
11809 return RETURN_ERR;
11810 }
11811
developer431128d2022-12-16 15:30:41 +080011812 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011813 fd = fopen(fname, "r");
11814 if (!fd) {
11815 return RETURN_ERR;
11816 }
11817
11818 if (keys == NULL) {
11819 ret = RETURN_ERR;
11820 goto close;
11821 }
11822
11823 keys_it = keys;
11824 while ((read = getline(&line, &len, fd)) != -1) {
11825 //Strip trailing new line if present
11826 if (read > 0 && line[read-1] == '\n') {
11827 line[read-1] = '\0';
11828 }
11829
11830 if(strcmp(line,"keyid=")) {
11831 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11832 if (!(pos = index(line, ' '))) {
11833 ret = RETURN_ERR;
11834 goto close;
11835 }
11836 pos++;
11837 //Here should be 00:00:00:00:00:00
11838 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11839 printf("Not supported MAC: %s\n", pos);
11840 }
11841 if (!(pos = index(pos, ' '))) {
11842 ret = RETURN_ERR;
11843 goto close;
11844 }
11845 pos++;
11846
11847 //The rest is PSK
11848 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11849 keys_it++;
11850
11851 if(--keysNumber <= 0)
11852 break;
11853 }
11854 }
11855
11856close:
11857 free(line);
11858 fclose(fd);
11859 return ret;
11860}
11861/* end of multi-psk support */
11862
11863INT wifi_setNeighborReports(UINT apIndex,
11864 UINT numNeighborReports,
11865 wifi_NeighborReport_t *neighborReports)
11866{
11867 char cmd[256] = { 0 };
11868 char hex_bssid[13] = { 0 };
11869 char bssid[18] = { 0 };
11870 char nr[256] = { 0 };
11871 char ssid[256];
11872 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011873 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011874 INT ret;
11875
11876 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011877 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011878 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011879 return RETURN_ERR;
11880 sprintf(cmd, "hostapd_cli show_neighbor -i %s | awk '{print $1 \" \" $2}' | xargs -n2 -r hostapd_cli remove_neighbor -i %s",interface_name,interface_name);
developer06a01d92022-09-07 16:32:39 +080011881 system(cmd);
11882
11883 for(unsigned int i = 0; i < numNeighborReports; i++)
11884 {
11885 memset(ssid, 0, sizeof(ssid));
11886 ret = wifi_getSSIDName(apIndex, ssid);
11887 if (ret != RETURN_OK)
11888 return RETURN_ERR;
11889
11890 memset(hex_ssid, 0, sizeof(hex_ssid));
11891 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11892 sprintf(hex_ssid + k,"%02x", ssid[j]);
11893
11894 snprintf(hex_bssid, sizeof(hex_bssid),
11895 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11896 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11897 snprintf(bssid, sizeof(bssid),
11898 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11899 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11900
11901 snprintf(nr, sizeof(nr),
11902 "%s" // bssid
11903 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11904 "%02hhx" // operclass
11905 "%02hhx" // channel
11906 "%02hhx", // phy_mode
11907 hex_bssid,
11908 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11909 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11910 neighborReports[i].opClass,
11911 neighborReports[i].channel,
11912 neighborReports[i].phyTable);
11913
11914 snprintf(cmd, sizeof(cmd),
11915 "hostapd_cli set_neighbor "
11916 "%s " // bssid
11917 "ssid=%s " // ssid
11918 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011919 "-i %s",
11920 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011921
11922 if (WEXITSTATUS(system(cmd)) != 0)
11923 {
11924 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11925 }
11926 }
11927
11928 return RETURN_OK;
11929}
11930
11931INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11932{
11933 return RETURN_OK;
11934}
11935
11936#ifdef _WIFI_HAL_TEST_
11937int main(int argc,char **argv)
11938{
11939 int index;
11940 INT ret=0;
11941 char buf[1024]="";
11942
11943 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11944 if(argc<3)
11945 {
11946 if(argc==2)
11947 {
11948 if(!strcmp(argv[1], "init"))
11949 return wifi_init();
11950 if(!strcmp(argv[1], "reset"))
11951 return wifi_reset();
11952 if(!strcmp(argv[1], "wifi_getHalVersion"))
11953 {
11954 char buffer[64];
11955 if(wifi_getHalVersion(buffer)==RETURN_OK)
11956 printf("Version: %s\n", buffer);
11957 else
11958 printf("Error in wifi_getHalVersion\n");
11959 return RETURN_OK;
11960 }
11961 }
11962 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11963 exit(-1);
11964 }
11965
11966 index = atoi(argv[2]);
11967 if(strstr(argv[1], "wifi_getApName")!=NULL)
11968 {
11969 wifi_getApName(index,buf);
11970 printf("Ap name is %s \n",buf);
11971 return 0;
11972 }
11973 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11974 {
11975 BOOL b = FALSE;
11976 BOOL *output_bool = &b;
11977 wifi_getRadioAutoChannelEnable(index,output_bool);
11978 printf("Channel enabled = %d \n",b);
11979 return 0;
11980 }
11981 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11982 {
11983 wifi_getApWpaEncryptionMode(index,buf);
11984 printf("encryption enabled = %s\n",buf);
11985 return 0;
11986 }
11987 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11988 {
11989 BOOL b = FALSE;
11990 BOOL *output_bool = &b;
11991 wifi_getApSsidAdvertisementEnable(index,output_bool);
11992 printf("advertisment enabled = %d\n",b);
11993 return 0;
11994 }
11995 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11996 {
11997 if(argc <= 3 )
11998 {
11999 printf("Insufficient arguments \n");
12000 exit(-1);
12001 }
12002
12003 char sta[20] = {'\0'};
12004 ULLONG handle= 0;
12005 strcpy(sta,argv[3]);
12006 mac_address_t st;
12007 mac_addr_aton(st,sta);
12008
12009 wifi_associated_dev_tid_stats_t tid_stats;
12010 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12011 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12012 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);
12013 }
12014
12015 if(strstr(argv[1], "getApEnable")!=NULL) {
12016 BOOL enable;
12017 ret=wifi_getApEnable(index, &enable);
12018 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12019 }
12020 else if(strstr(argv[1], "setApEnable")!=NULL) {
12021 BOOL enable = atoi(argv[3]);
12022 ret=wifi_setApEnable(index, enable);
12023 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12024 }
12025 else if(strstr(argv[1], "getApStatus")!=NULL) {
12026 char status[64];
12027 ret=wifi_getApStatus(index, status);
12028 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
12029 }
12030 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
12031 {
12032 wifi_getSSIDNameStatus(index,buf);
12033 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
12034 return 0;
12035 }
12036 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
12037 wifi_ssidTrafficStats2_t stats={0};
12038 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
12039 printf("%s %d: returns %d\n", argv[1], index, ret);
12040 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
12041 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
12042 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
12043 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
12044 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
12045 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
12046 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
12047 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
12048 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
12049 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
12050 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
12051 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
12052 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
12053 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
12054 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
12055 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
12056 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
12057 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
12058 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
12059 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
12060 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
12061 }
12062 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
12063 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
12064 UINT array_size=0;
12065 UINT i=0;
12066 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
12067 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12068 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
12069 printf(" neighbor %d:\n", i);
12070 printf(" ap_SSID =%s\n", pt->ap_SSID);
12071 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
12072 printf(" ap_Mode =%s\n", pt->ap_Mode);
12073 printf(" ap_Channel =%d\n", pt->ap_Channel);
12074 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
12075 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12076 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
12077 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
12078 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
12079 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
12080 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12081 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
12082 printf(" ap_Noise =%d\n", pt->ap_Noise);
12083 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
12084 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
12085 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
12086 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
12087 }
12088 if(neighbor_ap_array)
12089 free(neighbor_ap_array); //make sure to free the list
12090 }
12091 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
12092 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
12093 UINT array_size=0;
12094 UINT i=0;
12095 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
12096 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12097 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
12098 printf(" associated_dev %d:\n", i);
12099 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
12100 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
12101 printf(" cli_SNR =%d\n", pt->cli_SNR);
12102 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
12103 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
12104 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
12105 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
12106 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
12107 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
12108 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
12109 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
12110 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
12111 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
12112 }
12113 if(associated_dev_array)
12114 free(associated_dev_array); //make sure to free the list
12115 }
12116
12117 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12118 {
12119#define MAX_ARRAY_SIZE 64
12120 int i, array_size;
12121 char *p, *ch_str;
12122 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12123
12124 if(argc != 5)
12125 {
12126 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12127 exit(-1);
12128 }
12129 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12130
12131 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12132 {
12133 strtok_r(ch_str, ",", &p);
12134 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12135 }
12136 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12137 if(!array_size)
12138 array_size=1;//Need to print current channel statistics
12139 for(i=0; i<array_size; i++)
12140 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12141 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12142 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12143 input_output_channelStats_array[i].ch_number,\
12144 input_output_channelStats_array[i].ch_noise,\
12145 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12146 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12147 input_output_channelStats_array[i].ch_utilization_busy,\
12148 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12149 input_output_channelStats_array[i].ch_utilization_total);
12150 }
12151
12152 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12153 {
12154 if(argc <= 3 )
12155 {
12156 printf("Insufficient arguments \n");
12157 exit(-1);
12158 }
12159 char mac_addr[20] = {'\0'};
12160 wifi_device_t output_struct;
12161 int dev_index = atoi(argv[3]);
12162
12163 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12164 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12165 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);
12166 }
12167
12168 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12169 {
12170 if (argc <= 3)
12171 {
12172 printf("Insufficient arguments\n");
12173 exit(-1);
12174 }
12175 char args[256];
12176 wifi_NeighborReport_t *neighborReports;
12177
12178 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12179 if (!neighborReports)
12180 {
12181 printf("Failed to allocate memory");
12182 exit(-1);
12183 }
12184
12185 for (int i = 3; i < argc; ++i)
12186 {
12187 char *val;
12188 int j = 0;
12189 memset(args, 0, sizeof(args));
12190 strncpy(args, argv[i], sizeof(args));
12191 val = strtok(args, ";");
12192 while (val != NULL)
12193 {
12194 if (j == 0)
12195 {
12196 mac_addr_aton(neighborReports[i - 3].bssid, val);
12197 } else if (j == 1)
12198 {
12199 neighborReports[i - 3].info = strtol(val, NULL, 16);
12200 } else if (j == 2)
12201 {
12202 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12203 } else if (j == 3)
12204 {
12205 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12206 } else if (j == 4)
12207 {
12208 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12209 } else {
12210 printf("Insufficient arguments]n\n");
12211 exit(-1);
12212 }
12213 val = strtok(NULL, ";");
12214 j++;
12215 }
12216 }
12217
12218 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12219 if (ret != RETURN_OK)
12220 {
12221 printf("wifi_setNeighborReports ret = %d", ret);
12222 exit(-1);
12223 }
12224 }
12225 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12226 {
12227 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12228 printf("%s.\n", buf);
12229 else
12230 printf("Error returned\n");
12231 }
12232 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12233 {
12234 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12235 printf("%s.\n", buf);
12236 else
12237 printf("Error returned\n");
12238 }
12239 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12240 {
12241 if (argc <= 2)
12242 {
12243 printf("Insufficient arguments\n");
12244 exit(-1);
12245 }
12246 char buf[64]= {'\0'};
12247 wifi_getRadioOperatingChannelBandwidth(index,buf);
12248 printf("Current bandwidth is %s \n",buf);
12249 return 0;
12250 }
12251 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12252 {
12253 if (argc <= 5)
12254 {
12255 printf("Insufficient arguments\n");
12256 exit(-1);
12257 }
12258 UINT channel = atoi(argv[3]);
12259 UINT width = atoi(argv[4]);
12260 UINT beacon = atoi(argv[5]);
12261 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12262 printf("Result = %d", ret);
12263 }
12264
12265 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12266 return 0;
12267}
12268
12269#endif
12270
12271#ifdef WIFI_HAL_VERSION_3
12272
developer1e5aa162022-09-13 16:06:24 +080012273INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12274{
12275 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12276 if (bitMap & WIFI_BITRATE_1MBPS)
12277 strcat(BasicRate, "1,");
12278 if (bitMap & WIFI_BITRATE_2MBPS)
12279 strcat(BasicRate, "2,");
12280 if (bitMap & WIFI_BITRATE_5_5MBPS)
12281 strcat(BasicRate, "5.5,");
12282 if (bitMap & WIFI_BITRATE_6MBPS)
12283 strcat(BasicRate, "6,");
12284 if (bitMap & WIFI_BITRATE_9MBPS)
12285 strcat(BasicRate, "9,");
12286 if (bitMap & WIFI_BITRATE_11MBPS)
12287 strcat(BasicRate, "11,");
12288 if (bitMap & WIFI_BITRATE_12MBPS)
12289 strcat(BasicRate, "12,");
12290 if (bitMap & WIFI_BITRATE_18MBPS)
12291 strcat(BasicRate, "18,");
12292 if (bitMap & WIFI_BITRATE_24MBPS)
12293 strcat(BasicRate, "24,");
12294 if (bitMap & WIFI_BITRATE_36MBPS)
12295 strcat(BasicRate, "36,");
12296 if (bitMap & WIFI_BITRATE_48MBPS)
12297 strcat(BasicRate, "48,");
12298 if (bitMap & WIFI_BITRATE_54MBPS)
12299 strcat(BasicRate, "54,");
12300 if (strlen(BasicRate) != 0) // remove last comma
12301 BasicRate[strlen(BasicRate) - 1] = '\0';
12302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12303 return RETURN_OK;
12304}
12305
12306INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12307{
12308 UINT BitMap = 0;
12309 char *rate;
12310
12311 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12312 rate = strtok(BasicRatesList, ",");
12313 while(rate != NULL)
12314 {
12315 if (strcmp(rate, "1") == 0)
12316 BitMap |= WIFI_BITRATE_1MBPS;
12317 else if (strcmp(rate, "2") == 0)
12318 BitMap |= WIFI_BITRATE_2MBPS;
12319 else if (strcmp(rate, "5.5") == 0)
12320 BitMap |= WIFI_BITRATE_5_5MBPS;
12321 else if (strcmp(rate, "6") == 0)
12322 BitMap |= WIFI_BITRATE_6MBPS;
12323 else if (strcmp(rate, "9") == 0)
12324 BitMap |= WIFI_BITRATE_9MBPS;
12325 else if (strcmp(rate, "11") == 0)
12326 BitMap |= WIFI_BITRATE_11MBPS;
12327 else if (strcmp(rate, "12") == 0)
12328 BitMap |= WIFI_BITRATE_12MBPS;
12329 else if (strcmp(rate, "18") == 0)
12330 BitMap |= WIFI_BITRATE_18MBPS;
12331 else if (strcmp(rate, "24") == 0)
12332 BitMap |= WIFI_BITRATE_24MBPS;
12333 else if (strcmp(rate, "36") == 0)
12334 BitMap |= WIFI_BITRATE_36MBPS;
12335 else if (strcmp(rate, "48") == 0)
12336 BitMap |= WIFI_BITRATE_48MBPS;
12337 else if (strcmp(rate, "54") == 0)
12338 BitMap |= WIFI_BITRATE_54MBPS;
12339 rate = strtok(NULL, ",");
12340 }
12341 *basicRateBitMap = BitMap;
12342 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12343 return RETURN_OK;
12344}
12345
developer7c4cd202023-03-01 10:56:29 +080012346INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12347{
12348 int center_channel = 0;
12349 char central_channel_str[16] = {0};
12350 char config_file[32] = {0};
12351 struct params param = {0};
12352
12353 center_channel = util_unii_6g_centerfreq("HT320", channel);
12354 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12355 if (channel >= 193)
12356 return RETURN_ERR;
12357 if (channel >= 33) {
12358 if (channel > center_channel)
12359 center_channel += 32;
12360 else
12361 center_channel -= 32;
12362 }
12363 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12364 if (channel <= 29)
12365 return RETURN_ERR;
12366 }
12367 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12368 param.name = "eht_oper_centr_freq_seg0_idx";
12369 param.value = central_channel_str;
12370 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12371 wifi_hostapdWrite(config_file, &param, 1);
12372
12373 return RETURN_OK;
12374}
12375
12376INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12377{
12378 int op_class = 0;
12379 char config_file[32] = {0};
12380 char op_class_str[8] = {0};
12381 struct params param = {0};
12382
12383 if (bandwidth == 20)
12384 op_class = 131;
12385 else if (bandwidth == 40)
12386 op_class = 132;
12387 else if (bandwidth == 80)
12388 op_class = 133;
12389 else if (bandwidth == 160)
12390 op_class = 134;
12391 else if (bandwidth == 320)
12392 op_class = 137;
12393 else
12394 return RETURN_ERR;
12395 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12396 param.name = "op_class";
12397 param.value = op_class_str;
12398 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12399 wifi_hostapdWrite(config_file, &param, 1);
12400 return RETURN_OK;
12401}
12402
12403INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12404{
12405 char config_file[32] = {0};
12406 char buf [16] = {0};
12407
12408 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12409 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12410 return RETURN_ERR; // 6g band should set op_class
12411 *class = (UINT)strtoul(buf, NULL, 10);
12412
12413 return RETURN_OK;
12414}
12415
developer1e5aa162022-09-13 16:06:24 +080012416// 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 +080012417INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12418{
developer1e5aa162022-09-13 16:06:24 +080012419 char buf[128] = {0};
12420 char cmd[128] = {0};
12421 char config_file[64] = {0};
12422 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012423 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012424 wifi_radio_operationParam_t current_param;
12425
12426 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12427
12428 multiple_set = TRUE;
12429 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12430 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12431 return RETURN_ERR;
12432 }
12433 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12434 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12435 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12436 return RETURN_ERR;
12437 }
12438 }
developer5884e982022-10-06 10:52:50 +080012439
12440 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12441 bandwidth = 20;
12442 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12443 bandwidth = 40;
12444 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12445 bandwidth = 80;
12446 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12447 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012448 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12449 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012450 if (operationParam->autoChannelEnabled){
12451 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12452 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12453 return RETURN_ERR;
12454 }
12455 }else{
developer1e5aa162022-09-13 16:06:24 +080012456 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12457 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12458 return RETURN_ERR;
12459 }
12460 }
developer5884e982022-10-06 10:52:50 +080012461
developer7c4cd202023-03-01 10:56:29 +080012462 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12463 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12464 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12465 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12466 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12467 return RETURN_ERR;
12468 }
12469 }
12470
12471 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12472 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12473 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12474 return RETURN_ERR;
12475 }
12476 }
12477
developer1e5aa162022-09-13 16:06:24 +080012478 if (current_param.variant != operationParam->variant) {
12479 // Two different definition bit map, so need to check every bit.
12480 if (operationParam->variant & WIFI_80211_VARIANT_A)
12481 set_mode |= WIFI_MODE_A;
12482 if (operationParam->variant & WIFI_80211_VARIANT_B)
12483 set_mode |= WIFI_MODE_B;
12484 if (operationParam->variant & WIFI_80211_VARIANT_G)
12485 set_mode |= WIFI_MODE_G;
12486 if (operationParam->variant & WIFI_80211_VARIANT_N)
12487 set_mode |= WIFI_MODE_N;
12488 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12489 set_mode |= WIFI_MODE_AC;
12490 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12491 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012492 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12493 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012494 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12495 memset(buf, 0, sizeof(buf));
12496 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12497 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12498 return RETURN_ERR;
12499 }
12500 }
12501 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12502 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12503 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12504 return RETURN_ERR;
12505 }
12506 }
12507 if (current_param.beaconInterval != operationParam->beaconInterval) {
12508 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12509 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12510 return RETURN_ERR;
12511 }
12512 }
12513 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12514 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12515 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12516 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12517 return RETURN_ERR;
12518 }
12519 }
12520 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12521 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12522 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12523 return RETURN_ERR;
12524 }
12525 }
12526 if (current_param.guardInterval != operationParam->guardInterval) {
12527 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12528 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12529 return RETURN_ERR;
12530 }
12531 }
12532 if (current_param.transmitPower != operationParam->transmitPower) {
12533 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12534 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12535 return RETURN_ERR;
12536 }
12537 }
12538 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12539 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12540 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12541 return RETURN_ERR;
12542 }
12543 }
12544 if (current_param.obssCoex != operationParam->obssCoex) {
12545 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12546 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12547 return RETURN_ERR;
12548 }
12549 }
12550 if (current_param.stbcEnable != operationParam->stbcEnable) {
12551 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12552 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12553 return RETURN_ERR;
12554 }
12555 }
developer5735d092023-09-19 20:12:26 +080012556 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12557 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12558 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12559 return RETURN_ERR;
12560 }
12561 }
developer1e5aa162022-09-13 16:06:24 +080012562
12563 // if enable is true, then restart the radio
12564 wifi_setRadioEnable(index, FALSE);
12565 if (operationParam->enable == TRUE)
12566 wifi_setRadioEnable(index, TRUE);
12567 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12568
developer06a01d92022-09-07 16:32:39 +080012569 return RETURN_OK;
12570}
12571
12572INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12573{
developer1e5aa162022-09-13 16:06:24 +080012574 char band[64] = {0};
12575 char buf[256] = {0};
12576 char config_file[64] = {0};
12577 char cmd[128] = {0};
12578 int ret = RETURN_ERR;
12579 int mode = 0;
12580 ULONG channel = 0;
12581 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012582
12583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12584 printf("Entering %s index = %d\n", __func__, (int)index);
12585
developer1e5aa162022-09-13 16:06:24 +080012586 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12587 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12588 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012589 {
developer1e5aa162022-09-13 16:06:24 +080012590 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012591 return RETURN_ERR;
12592 }
12593 operationParam->enable = enabled;
12594
12595 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012596 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012597 {
developer1e5aa162022-09-13 16:06:24 +080012598 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012599 return RETURN_ERR;
12600 }
12601
12602 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012603 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012604 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012605 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012606 else if (!strcmp(band, "6GHz"))
12607 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012608 else
12609 {
developer1e5aa162022-09-13 16:06:24 +080012610 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012611 band);
12612 }
12613
developer1e5aa162022-09-13 16:06:24 +080012614 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12615 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12616 operationParam->channel = 0;
12617 operationParam->autoChannelEnabled = TRUE;
12618 } else {
12619 operationParam->channel = strtol(buf, NULL, 10);
12620 operationParam->autoChannelEnabled = FALSE;
12621 }
12622
developer06a01d92022-09-07 16:32:39 +080012623 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012624 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12625 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12626 return RETURN_ERR;
12627 }
developer06a01d92022-09-07 16:32:39 +080012628 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12629 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12630 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012631 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012632 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12633 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012634 else
12635 {
developer1e5aa162022-09-13 16:06:24 +080012636 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12637 return false;
developer06a01d92022-09-07 16:32:39 +080012638 }
12639
developer7c4cd202023-03-01 10:56:29 +080012640 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12641 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12642 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12643 return RETURN_ERR;
12644 }
12645 }
12646
developer1e5aa162022-09-13 16:06:24 +080012647 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12648 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12649 return RETURN_ERR;
12650 }
12651 // Two different definition bit map, so need to check every bit.
12652 if (mode & WIFI_MODE_A)
12653 operationParam->variant |= WIFI_80211_VARIANT_A;
12654 if (mode & WIFI_MODE_B)
12655 operationParam->variant |= WIFI_80211_VARIANT_B;
12656 if (mode & WIFI_MODE_G)
12657 operationParam->variant |= WIFI_80211_VARIANT_G;
12658 if (mode & WIFI_MODE_N)
12659 operationParam->variant |= WIFI_80211_VARIANT_N;
12660 if (mode & WIFI_MODE_AC)
12661 operationParam->variant |= WIFI_80211_VARIANT_AC;
12662 if (mode & WIFI_MODE_AX)
12663 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012664 if (mode & WIFI_MODE_BE)
12665 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012666 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12667 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12668 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012669 }
developer1e5aa162022-09-13 16:06:24 +080012670 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12671 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12672 return RETURN_ERR;
12673 }
12674 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12675 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12676 return RETURN_ERR;
12677 }
developer06a01d92022-09-07 16:32:39 +080012678
developer1e5aa162022-09-13 16:06:24 +080012679 memset(buf, 0, sizeof(buf));
12680 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12681 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12682 return RETURN_ERR;
12683 }
12684 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12685
12686 memset(buf, 0, sizeof(buf));
12687 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12688 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12689 return RETURN_ERR;
12690 }
12691 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12692
12693 memset(buf, 0, sizeof(buf));
12694 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12695 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12696
12697 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12698 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12699 return RETURN_ERR;
12700 }
12701 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12702 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12703 return RETURN_ERR;
12704 }
12705
12706 memset(buf, 0, sizeof(buf));
12707 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12708 if (strcmp(buf, "-1") == 0) {
12709 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12710 operationParam->ctsProtection = FALSE;
12711 } else {
12712 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12713 operationParam->ctsProtection = TRUE;
12714 }
12715
12716 memset(buf, 0, sizeof(buf));
12717 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12718 if (strcmp(buf, "0") == 0)
12719 operationParam->obssCoex = FALSE;
12720 else
12721 operationParam->obssCoex = TRUE;
12722
12723 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12724 _syscmd(cmd, buf, sizeof(buf));
12725 if (strlen(buf) != 0)
12726 operationParam->stbcEnable = TRUE;
12727 else
12728 operationParam->stbcEnable = FALSE;
12729
developer5735d092023-09-19 20:12:26 +080012730 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12731 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12732 return RETURN_ERR;
12733 }
developer1e5aa162022-09-13 16:06:24 +080012734
12735 // Below value is hardcoded
12736
12737 operationParam->numSecondaryChannels = 0;
12738 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12739 operationParam->channelSecondary[i] = 0;
12740 }
12741 operationParam->csa_beacon_count = 15;
12742 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012743
12744 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12745 return RETURN_OK;
12746}
12747
12748static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12749{
developerc086fb72022-10-04 10:18:22 +080012750 int max_radio_num = 0;
12751
12752 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012753 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012754 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12755 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012756 }
12757
developerc086fb72022-10-04 10:18:22 +080012758 return (arrayIndex * max_radio_num) + radioIndex;
12759}
developer06a01d92022-09-07 16:32:39 +080012760
developerc086fb72022-10-04 10:18:22 +080012761wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12762 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12763 return WIFI_BITRATE_1MBPS;
12764 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12765 return WIFI_BITRATE_2MBPS;
12766 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12767 return WIFI_BITRATE_5_5MBPS;
12768 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12769 return WIFI_BITRATE_6MBPS;
12770 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12771 return WIFI_BITRATE_9MBPS;
12772 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12773 return WIFI_BITRATE_11MBPS;
12774 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12775 return WIFI_BITRATE_12MBPS;
12776 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12777 return WIFI_BITRATE_18MBPS;
12778 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12779 return WIFI_BITRATE_24MBPS;
12780 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12781 return WIFI_BITRATE_36MBPS;
12782 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12783 return WIFI_BITRATE_48MBPS;
12784 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12785 return WIFI_BITRATE_54MBPS;
12786 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012787}
12788
developer1d57d002022-10-12 18:03:15 +080012789INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12790{
12791 if (beacon == WIFI_BITRATE_1MBPS)
12792 strcpy(beacon_str, "1Mbps");
12793 else if (beacon == WIFI_BITRATE_2MBPS)
12794 strcpy(beacon_str, "2Mbps");
12795 else if (beacon == WIFI_BITRATE_5_5MBPS)
12796 strcpy(beacon_str, "5.5Mbps");
12797 else if (beacon == WIFI_BITRATE_6MBPS)
12798 strcpy(beacon_str, "6Mbps");
12799 else if (beacon == WIFI_BITRATE_9MBPS)
12800 strcpy(beacon_str, "9Mbps");
12801 else if (beacon == WIFI_BITRATE_11MBPS)
12802 strcpy(beacon_str, "11Mbps");
12803 else if (beacon == WIFI_BITRATE_12MBPS)
12804 strcpy(beacon_str, "12Mbps");
12805 else if (beacon == WIFI_BITRATE_18MBPS)
12806 strcpy(beacon_str, "18Mbps");
12807 else if (beacon == WIFI_BITRATE_24MBPS)
12808 strcpy(beacon_str, "24Mbps");
12809 else if (beacon == WIFI_BITRATE_36MBPS)
12810 strcpy(beacon_str, "36Mbps");
12811 else if (beacon == WIFI_BITRATE_48MBPS)
12812 strcpy(beacon_str, "48Mbps");
12813 else if (beacon == WIFI_BITRATE_54MBPS)
12814 strcpy(beacon_str, "54Mbps");
12815 return RETURN_OK;
12816}
12817
developer74ed4192023-09-21 17:15:17 +080012818void checkVapStatus(int apIndex, bool *enable)
12819{
12820 char if_name[16] = {0};
12821 char cmd[128] = {0};
12822 char buf[128] = {0};
12823
12824 *enable = FALSE;
12825 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12826 return;
12827
12828 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12829 _syscmd(cmd, buf, sizeof(buf));
12830 if (strlen(buf) > 0)
12831 *enable = TRUE;
12832 return;
12833}
12834
developerefb790a2023-12-26 18:58:32 +080012835INT wifi_getVapInfoMisc(int vap_index)
12836{
12837 char config_file[MAX_BUF_SIZE] = {0};
12838
12839 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX,vap_index);
12840 wifi_hostapdRead(config_file,"ssid",vap_info[vap_index].ssid, MAX_BUF_SIZE);
12841 wifi_hostapdRead(config_file,"wpa", vap_info[vap_index].wpa, MAX_BUF_SIZE);
12842 wifi_hostapdRead(config_file,"wpa_key_mgmt", vap_info[vap_index].wpa_key_mgmt, MAX_BUF_SIZE);
12843 wifi_hostapdRead(config_file,"wpa_passphrase", vap_info[vap_index].wpa_passphrase, MAX_BUF_SIZE);
12844 wifi_hostapdRead(config_file,"ap_isolate", vap_info[vap_index].ap_isolate, MAX_BUF_SIZE);
12845 wifi_hostapdRead(config_file,"macaddr_acl", vap_info[vap_index].macaddr_acl, MAX_BUF_SIZE);
12846 wifi_hostapdRead(config_file,"bss_transition", vap_info[vap_index].bss_transition, MAX_BUF_SIZE);
12847 wifi_hostapdRead(config_file,"ignore_broadcast_ssid", vap_info[vap_index].ignore_broadcast_ssid, MAX_BUF_SIZE);
12848 wifi_hostapdRead(config_file, "max_num_sta", vap_info[vap_index].max_sta, MAX_BUF_SIZE);
12849 return RETURN_OK;
12850}
12851
12852int wifi_Syncthread(void *arg)
12853{
12854 int radio_idx = 0, i = 0;
12855 int vap_index = 0;
developera2af46a2024-01-04 19:11:23 +080012856 int max_radio = 0;
developerefb790a2023-12-26 18:58:32 +080012857
developera2af46a2024-01-04 19:11:23 +080012858 wifi_getMaxRadioNumber(&max_radio);
developerefb790a2023-12-26 18:58:32 +080012859 while (1)
12860 {
12861 sleep(5);
developera2af46a2024-01-04 19:11:23 +080012862 for (radio_idx = 0; radio_idx < max_radio; radio_idx++)
developerefb790a2023-12-26 18:58:32 +080012863 {
12864 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
12865 {
12866 vap_index = array_index_to_vap_index(radio_idx, i);
12867 if (vap_index >= 0)
12868 wifi_getVapInfoMisc(vap_index);
12869 }
12870 }
12871 syn_flag = 1;
12872 }
12873 return 0;
12874}
12875
developer06a01d92022-09-07 16:32:39 +080012876INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12877{
developerc086fb72022-10-04 10:18:22 +080012878 INT mode = 0;
12879 INT ret = -1;
12880 INT output = 0;
12881 int i = 0;
12882 int vap_index = 0;
12883 BOOL enabled = FALSE;
12884 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012885 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012886
developer06a01d92022-09-07 16:32:39 +080012887
12888 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12889 printf("Entering %s index = %d\n", __func__, (int)index);
12890
developera77d84b2023-02-22 16:10:50 +080012891 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012892 {
developerc086fb72022-10-04 10:18:22 +080012893 map->vap_array[i].radio_index = index;
12894
developer06a01d92022-09-07 16:32:39 +080012895 vap_index = array_index_to_vap_index(index, i);
12896 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012897 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012898
developerc086fb72022-10-04 10:18:22 +080012899 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012900
12901 map->vap_array[i].vap_index = vap_index;
12902
12903 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012904 ret = wifi_getApName(vap_index, buf);
12905 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012906 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12907
developerc086fb72022-10-04 10:18:22 +080012908 return RETURN_ERR;
12909 }
12910 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12911
12912 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012913 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012914 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012915 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012916 return RETURN_ERR;
12917 }
12918 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
developer06a01d92022-09-07 16:32:39 +080012919
developer74ed4192023-09-21 17:15:17 +080012920 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012921 map->vap_array[i].u.bss_info.enabled = enabled;
12922
developerc086fb72022-10-04 10:18:22 +080012923 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12924 if (ret != RETURN_OK) {
12925 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12926 return RETURN_ERR;
12927 }
developer06a01d92022-09-07 16:32:39 +080012928 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012929
12930 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12931 if (ret != RETURN_OK) {
12932 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12933 return RETURN_ERR;
12934 }
12935 map->vap_array[i].u.bss_info.isolation = enabled;
12936
12937 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12938 if (ret != RETURN_OK) {
12939 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12940 return RETURN_ERR;
12941 }
12942 map->vap_array[i].u.bss_info.bssMaxSta = output;
12943
12944 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12945 if (ret != RETURN_OK) {
12946 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12947 return RETURN_ERR;
12948 }
12949 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012950
developerc086fb72022-10-04 10:18:22 +080012951 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12952 if (ret != RETURN_OK) {
12953 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12954 return RETURN_ERR;
12955 }
12956 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012957
developerc086fb72022-10-04 10:18:22 +080012958 ret = wifi_getApSecurity(vap_index, &security);
12959 if (ret != RETURN_OK) {
12960 printf("%s: wifi_getApSecurity return error\n", __func__);
12961 return RETURN_ERR;
12962 }
12963 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012964
developerc086fb72022-10-04 10:18:22 +080012965 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12966 if (ret != RETURN_OK) {
12967 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12968 return RETURN_ERR;
12969 }
12970 if (mode == 0)
12971 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12972 else
12973 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12974 if (mode == 1)
12975 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12976 else if (mode == 2)
12977 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012978
developerc086fb72022-10-04 10:18:22 +080012979 ret = wifi_getApWmmEnable(vap_index, &enabled);
12980 if (ret != RETURN_OK) {
12981 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12982 return RETURN_ERR;
12983 }
12984 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012985
developerc086fb72022-10-04 10:18:22 +080012986 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12987 if (ret != RETURN_OK) {
12988 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012989 return RETURN_ERR;
12990 }
developerc086fb72022-10-04 10:18:22 +080012991 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012992
12993 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012994 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012995 if (ret != RETURN_OK) {
12996 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12997 return RETURN_ERR;
12998 }
12999 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080013000
developerc086fb72022-10-04 10:18:22 +080013001 memset(buf, 0, sizeof(buf));
13002 ret = wifi_getBaseBSSID(vap_index, buf);
13003 if (ret != RETURN_OK) {
13004 printf("%s: wifi_getBaseBSSID return error\n", __func__);
13005 return RETURN_ERR;
13006 }
13007 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13008 &map->vap_array[i].u.bss_info.bssid[0],
13009 &map->vap_array[i].u.bss_info.bssid[1],
13010 &map->vap_array[i].u.bss_info.bssid[2],
13011 &map->vap_array[i].u.bss_info.bssid[3],
13012 &map->vap_array[i].u.bss_info.bssid[4],
13013 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080013014 // fprintf(stderr, "%s index %d: mac: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", __func__, vap_index, map->vap_array[i].u.bss_info.bssid[0], map->vap_array[i].u.bss_info.bssid[1], map->vap_array[i].u.bss_info.bssid[2], map->vap_array[i].u.bss_info.bssid[3], map->vap_array[i].u.bss_info.bssid[4], map->vap_array[i].u.bss_info.bssid[5]);
13015
13016 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
13017 if (ret != RETURN_OK) {
13018 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
13019 return RETURN_ERR;
13020 }
13021 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080013022
13023 ret = wifi_getApWpsEnable(vap_index, &enabled);
13024 if (ret != RETURN_OK) {
13025 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
13026 return RETURN_ERR;
13027 }
13028
13029 map->vap_array[i].u.bss_info.wps.enable = enabled;
13030
developera77d84b2023-02-22 16:10:50 +080013031 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080013032 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080013033 }
developerefb790a2023-12-26 18:58:32 +080013034
13035 if (!tflag) {
13036 result = pthread_create(&pthread_id, NULL, wifi_Syncthread,NULL);
13037 if (result != 0)
13038 printf("%s %d fail create sync thread\n", __func__, __LINE__);
13039 else
13040 tflag = 1;
13041 }
13042
developer06a01d92022-09-07 16:32:39 +080013043 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13044 return RETURN_OK;
13045}
13046
developer431128d2022-12-16 15:30:41 +080013047
developerd946fd62022-12-08 18:03:28 +080013048static int prepareInterface(UINT apIndex, char *new_interface)
13049{
13050 char cur_interface[16] = {0};
13051 char config_file[128] = {0};
13052 char cmd[128] = {0};
13053 char buf[16] = {0};
13054 int max_radio_num = 0;
13055 int radioIndex = -1;
13056 int phyIndex = -1;
13057
13058 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13059 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13060
13061 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
13062 wifi_getMaxRadioNumber(&max_radio_num);
13063 radioIndex = apIndex % max_radio_num;
13064 phyIndex = radio_index_to_phy(radioIndex);
13065 // disable and del old interface, then add new interface
13066 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080013067 if (!(apIndex/max_radio_num)) {
13068 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
13069 _syscmd(cmd, buf, sizeof(buf));
13070 }
developerd946fd62022-12-08 18:03:28 +080013071 }
developer431128d2022-12-16 15:30:41 +080013072 // update the vap status file
13073 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13074 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080013075 return RETURN_OK;
13076}
13077
developer06a01d92022-09-07 16:32:39 +080013078INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13079{
developerd946fd62022-12-08 18:03:28 +080013080 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013081 unsigned int i;
13082 wifi_vap_info_t *vap_info = NULL;
13083 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080013084 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080013085 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080013086 char buf[256] = {0};
13087 char cmd[128] = {0};
13088 char config_file[64] = {0};
13089 char bssid[32] = {0};
13090 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080013091 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080013092
13093 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13094 printf("Entering %s index = %d\n", __func__, (int)index);
13095 for (i = 0; i < map->num_vaps; i++)
13096 {
developer1d57d002022-10-12 18:03:15 +080013097 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080013098 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080013099
13100 // Check vap status file to enable multiple ap if the system boot.
13101 checkVapStatus(vap_info->vap_index, &enable);
13102 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080013103 continue;
developer06a01d92022-09-07 16:32:39 +080013104
developer1d57d002022-10-12 18:03:15 +080013105 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13106
developer431128d2022-12-16 15:30:41 +080013107 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13108 enable = FALSE;
13109
13110 // multi-ap first up need to copy current radio config
13111 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080013112 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13113 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080013114 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13115 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13116 } else {
13117 // Check whether the interface name is valid or this ap change it.
13118 int apIndex = -1;
13119 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13120 if (apIndex != -1 && apIndex != vap_info->vap_index)
13121 continue;
13122 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080013123 }
developer06a01d92022-09-07 16:32:39 +080013124
developer1d57d002022-10-12 18:03:15 +080013125 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080013126 params[0].name = "interface";
13127 params[0].value = vap_info->vap_name;
13128 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13129 params[1].name = "bssid";
13130 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080013131 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080013132 params[2].name = "wpa_psk_file";
13133 params[2].value = psk_file;
13134
13135 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13136 wifi_hostapdWrite(config_file, params, 3);
13137
13138 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13139 _syscmd(cmd, buf, sizeof(buf));
13140
13141 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13142 if (ret != RETURN_OK) {
13143 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13144 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013145 }
developer1d57d002022-10-12 18:03:15 +080013146
13147 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13148 if (ret != RETURN_OK) {
13149 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13150 return RETURN_ERR;
13151 }
13152
13153 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13154 if (ret != RETURN_OK) {
13155 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13156 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013157 }
13158
developer1d57d002022-10-12 18:03:15 +080013159 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13160 if (ret != RETURN_OK) {
13161 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13162 return RETURN_ERR;
13163 }
developer06a01d92022-09-07 16:32:39 +080013164
developer1d57d002022-10-12 18:03:15 +080013165 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13166 if (ret != RETURN_OK) {
13167 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13168 return RETURN_ERR;
13169 }
developer06a01d92022-09-07 16:32:39 +080013170
developer1d57d002022-10-12 18:03:15 +080013171 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13172 if (ret != RETURN_OK) {
13173 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13174 return RETURN_ERR;
13175 }
13176
developer804c64f2022-10-19 13:54:40 +080013177 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080013178 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080013179 }else {
13180 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080013181 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080013182 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13183 _syscmd(cmd, buf, sizeof(buf));
13184 }else{
developer1d57d002022-10-12 18:03:15 +080013185 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080013186 }
developer1d57d002022-10-12 18:03:15 +080013187 }
13188
13189 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13190 if (ret != RETURN_OK) {
13191 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13192 return RETURN_ERR;
13193 }
13194
13195 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13196 if (ret != RETURN_OK) {
13197 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13198 return RETURN_ERR;
13199 }
13200
13201 memset(buf, 0, sizeof(buf));
13202 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13203 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
13204 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13205 if (ret != RETURN_OK) {
13206 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13207 return RETURN_ERR;
13208 }
13209
developer1d57d002022-10-12 18:03:15 +080013210 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13211 if (ret != RETURN_OK) {
13212 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13213 return RETURN_ERR;
13214 }
13215
13216 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13217 if (ret != RETURN_OK) {
13218 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13219 return RETURN_ERR;
13220 }
developer06a01d92022-09-07 16:32:39 +080013221
developer894affa2023-05-10 18:13:19 +080013222 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
13223 if (ret != RETURN_OK) {
13224 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
13225 return RETURN_ERR;
13226 }
13227
developer2f995fb2023-02-24 10:40:44 +080013228 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080013229 if (vap_info->u.bss_info.enabled == TRUE)
13230 wifi_setApEnable(vap_info->vap_index, TRUE);
13231
developer2f995fb2023-02-24 10:40:44 +080013232 multiple_set = FALSE;
13233
13234 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080013235 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080013236 // The set wps methods function should check whether wps is configured.
13237 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
13238 if (ret != RETURN_OK) {
13239 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
13240 return RETURN_ERR;
13241 }
13242 // wifi_setApWpsConfigMethodsEnabled only write to config.
13243 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13244 if (ret != RETURN_OK) {
13245 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13246 return RETURN_ERR;
13247 }
13248 }
developer2f995fb2023-02-24 10:40:44 +080013249
developer894affa2023-05-10 18:13:19 +080013250 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013251 }
developerfb09ba62023-06-09 17:03:21 +080013252
13253 // IGMP Snooping enable should be placed after all hostapd_reload.
13254 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13255 if (ret != RETURN_OK) {
13256 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13257 return RETURN_ERR;
13258 }
13259
developer06a01d92022-09-07 16:32:39 +080013260 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13261 return RETURN_OK;
13262}
13263
13264int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13265{
13266 char *token, *next;
13267 const char s[2] = ",";
13268 int count =0;
13269
13270 /* get the first token */
13271 token = strtok_r(pchannels, s, &next);
13272
13273 /* walk through other tokens */
13274 while( token != NULL && count < MAX_CHANNELS) {
13275 chlistptr->channels_list[count++] = atoi(token);
13276 token = strtok_r(NULL, s, &next);
13277 }
13278
13279 return count;
13280}
13281
13282static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13283{
13284 INT status;
13285 wifi_channels_list_t *chlistp;
13286 CHAR output_string[64];
13287 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013288 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013289 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013290
13291 if(rcap == NULL)
13292 {
13293 return RETURN_ERR;
13294 }
13295
13296 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013297 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013298
developer1e5aa162022-09-13 16:06:24 +080013299 if (band == band_2_4)
13300 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13301 else if (band == band_5)
13302 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13303 else if (band == band_6)
13304 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013305
13306 chlistp = &(rcap->channel_list[0]);
13307 memset(pchannels, 0, sizeof(pchannels));
13308
13309 /* possible number of radio channels */
13310 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13311 {
13312 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13313 }
13314 /* Number of channels and list*/
13315 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13316
13317 /* autoChannelSupported */
13318 /* always ON with wifi_getRadioAutoChannelSupported */
13319 rcap->autoChannelSupported = TRUE;
13320
13321 /* DCSSupported */
13322 /* always ON with wifi_getRadioDCSSupported */
13323 rcap->DCSSupported = TRUE;
13324
13325 /* zeroDFSSupported - TBD */
13326 rcap->zeroDFSSupported = FALSE;
13327
13328 /* Supported Country List*/
13329 memset(output_string, 0, sizeof(output_string));
13330 status = wifi_getRadioCountryCode(radioIndex, output_string);
13331 if( status != 0 ) {
13332 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13333 return RETURN_ERR;
13334 } else {
13335 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13336 }
13337 if(!strcmp(output_string,"US")){
13338 rcap->countrySupported[0] = wifi_countrycode_US;
13339 rcap->countrySupported[1] = wifi_countrycode_CA;
13340 } else if (!strcmp(output_string,"CA")) {
13341 rcap->countrySupported[0] = wifi_countrycode_CA;
13342 rcap->countrySupported[1] = wifi_countrycode_US;
13343 } else {
13344 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13345 }
13346
13347 rcap->numcountrySupported = 2;
13348
13349 /* csi */
13350 rcap->csi.maxDevices = 8;
13351 rcap->csi.soudingFrameSupported = TRUE;
13352
developer7930d352022-12-21 17:55:42 +080013353 wifi_GetInterfaceName(radioIndex, interface_name);
13354 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013355
13356 /* channelWidth - all supported bandwidths */
13357 int i=0;
13358 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013359
13360 /* mode - all supported variants */
13361 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13362 wifi_getRadioSupportedStandards(radioIndex, output_string);
13363
developer06a01d92022-09-07 16:32:39 +080013364 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13365 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13366 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013367 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013368
developer7c4cd202023-03-01 10:56:29 +080013369 if (strstr(output_string, "n") != NULL)
13370 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13371 if (strstr(output_string, "ax") != NULL)
13372 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13373 if (strstr(output_string, "be") != NULL)
13374 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13375 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013376 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13377 WIFI_CHANNELBANDWIDTH_40MHZ |
13378 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013379 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013380
developer7c4cd202023-03-01 10:56:29 +080013381 if (strstr(output_string, "n") != NULL)
13382 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13383 if (strstr(output_string, "ac") != NULL)
13384 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13385 if (strstr(output_string, "ax") != NULL)
13386 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13387 if (strstr(output_string, "be") != NULL)
13388 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13389 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13390 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13391 WIFI_CHANNELBANDWIDTH_40MHZ |
13392 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013393 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013394
13395 if (strstr(output_string, "be") != NULL) {
13396 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13397 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13398 }
developer06a01d92022-09-07 16:32:39 +080013399 }
developer7c4cd202023-03-01 10:56:29 +080013400
developer06a01d92022-09-07 16:32:39 +080013401 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13402 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13403
13404 /* supportedBitRate - all supported bitrates */
13405 rcap->supportedBitRate[i] = 0;
13406 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13407 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13408 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13409 }
developer1e5aa162022-09-13 16:06:24 +080013410 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013411 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13412 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13413 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13414 }
13415
13416
13417 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13418 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13419 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13420 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13421 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13422 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13423 rcap->cipherSupported = 0;
13424 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13425 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13426
13427 return RETURN_OK;
13428}
13429
13430INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13431{
developer30423732022-12-01 16:17:49 +080013432 INT status = 0, radioIndex = 0;
13433 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013434 int iter = 0;
developer30423732022-12-01 16:17:49 +080013435 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013436 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013437 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013438
13439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13440
13441 memset(cap, 0, sizeof(wifi_hal_capability_t));
13442
13443 /* version */
13444 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13445 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13446
13447 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013448 wifi_getMaxRadioNumber(&max_num_radios);
13449 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013450
13451 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13452 {
13453 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13454 if (status != 0) {
13455 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13456 return RETURN_ERR;
13457 }
13458
13459 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13460 {
developer804c64f2022-10-19 13:54:40 +080013461 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013462 {
13463 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13464 return RETURN_ERR;
13465 }
13466 iface_info = &cap->wifi_prop.interface_map[iter];
13467 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13468 iface_info->rdk_radio_index = radioIndex;
13469 memset(output, 0, sizeof(output));
13470 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13471 {
13472 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13473 }
13474 // TODO: bridge name
13475 // TODO: vlan id
13476 // TODO: primary
13477 iface_info->index = array_index_to_vap_index(radioIndex, j);
13478 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013479 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013480 {
13481 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13482 }
13483 iter++;
13484 }
13485 }
13486
13487 cap->BandSteeringSupported = FALSE;
13488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13489 return RETURN_OK;
13490}
13491
developer9df4e652022-10-11 11:27:38 +080013492INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13493{
13494 struct params h_config={0};
13495 char config_file[64] = {0};
13496
13497 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13498
13499 h_config.name = "okc";
13500 h_config.value = okc_enable?"1":"0";
13501
13502 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13503 wifi_hostapdWrite(config_file, &h_config, 1);
13504 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13505
13506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13507 return RETURN_OK;
13508}
13509
13510INT wifi_setSAEMFP(int ap_index, BOOL enable)
13511{
13512 struct params h_config={0};
13513 char config_file[64] = {0};
13514 char buf[128] = {0};
13515
13516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13517
13518 h_config.name = "sae_require_mfp";
13519 h_config.value = enable?"1":"0";
13520
13521 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13522 wifi_hostapdWrite(config_file, &h_config, 1);
13523 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13524
13525 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13526 return RETURN_OK;
13527}
13528
13529INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13530{
13531 struct params h_config={0};
13532 char config_file[64] = {0};
13533 char buf[128] = {0};
13534
13535 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13536
13537 h_config.name = "sae_pwe";
13538 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13539 h_config.value = buf;
13540
13541 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13542 wifi_hostapdWrite(config_file, &h_config, 1);
13543 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13544
13545 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13546 return RETURN_OK;
13547}
13548
13549INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13550{
13551 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13552 struct params h_config={0};
13553 char config_file[64] = {0};
13554
13555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13556
13557 h_config.name = "wpa_disable_eapol_key_retries";
13558 h_config.value = disable_EAPOL_retries?"1":"0";
13559
13560 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13561 wifi_hostapdWrite(config_file, &h_config, 1);
13562 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13563
13564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13565 return RETURN_OK;
13566}
13567
developer06a01d92022-09-07 16:32:39 +080013568INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13569{
developer587c1b62022-09-27 15:58:59 +080013570 char buf[128] = {0};
13571 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013572 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013573 char password[64] = {0};
13574 char mfp[32] = {0};
13575 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013576 BOOL okc_enable = FALSE;
13577 BOOL sae_MFP = FALSE;
13578 BOOL disable_EAPOL_retries = TRUE;
13579 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013580 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013581 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013582
13583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13584
13585 multiple_set = TRUE;
13586 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13587 if (security->mode == wifi_security_mode_none) {
13588 strcpy(wpa_mode, "None");
13589 } else if (security->mode == wifi_security_mode_wpa_personal)
13590 strcpy(wpa_mode, "WPA-Personal");
13591 else if (security->mode == wifi_security_mode_wpa2_personal)
13592 strcpy(wpa_mode, "WPA2-Personal");
13593 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13594 strcpy(wpa_mode, "WPA-WPA2-Personal");
13595 else if (security->mode == wifi_security_mode_wpa_enterprise)
13596 strcpy(wpa_mode, "WPA-Enterprise");
13597 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13598 strcpy(wpa_mode, "WPA2-Enterprise");
13599 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13600 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013601 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013602 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013603 okc_enable = TRUE;
13604 sae_MFP = TRUE;
13605 sae_pwe = 2;
13606 disable_EAPOL_retries = FALSE;
13607 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013608 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013609 okc_enable = TRUE;
13610 sae_MFP = TRUE;
13611 sae_pwe = 2;
13612 disable_EAPOL_retries = FALSE;
13613 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013614 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013615 sae_MFP = TRUE;
13616 sae_pwe = 2;
13617 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013618 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013619 strcpy(wpa_mode, "OWE");
13620 sae_MFP = TRUE;
13621 sae_pwe = 2;
13622 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013623 }
13624
13625 band = wifi_index_to_band(ap_index);
13626 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13627 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13628 return RETURN_ERR;
13629 }
developer587c1b62022-09-27 15:58:59 +080013630
13631 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013632 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013633 wifi_setSAEMFP(ap_index, sae_MFP);
13634 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013635 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013636
developerae432c62023-04-24 11:07:20 +080013637 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013638 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_pass || security->u.key.type == wifi_security_key_type_psk_sae) {
13639 int key_len = strlen(security->u.key.key);
13640 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13641 if (key_len == 64) { // set wpa_psk
13642 strncpy(password, security->u.key.key, 64); // 64 characters
13643 password[64] = '\0';
13644 wifi_setApSecurityPreSharedKey(ap_index, password);
13645 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13646 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13647 strncpy(password, security->u.key.key, 63);
13648 password[63] = '\0';
13649 wifi_setApSecurityKeyPassphrase(ap_index, password);
13650 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13651 } else
13652 return RETURN_ERR;
13653 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013654 }
13655 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13656 params.name = "sae_password";
13657 params.value = security->u.key.key;
13658 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013659 } else { // remove sae_password
13660 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13661 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013662 }
13663 }
developer587c1b62022-09-27 15:58:59 +080013664
13665 if (security->mode != wifi_security_mode_none) {
13666 memset(&params, 0, sizeof(params));
13667 params.name = "wpa_pairwise";
13668 if (security->encr == wifi_encryption_tkip)
13669 params.value = "TKIP";
13670 else if (security->encr == wifi_encryption_aes)
13671 params.value = "CCMP";
13672 else if (security->encr == wifi_encryption_aes_tkip)
13673 params.value = "TKIP CCMP";
13674 wifi_hostapdWrite(config_file, &params, 1);
13675 }
13676
13677 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013678 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013679 else if (security->mfp == wifi_mfp_cfg_optional)
13680 strcpy(mfp, "Optional");
13681 else if (security->mfp == wifi_mfp_cfg_required)
13682 strcpy(mfp, "Required");
13683 wifi_setApSecurityMFPConfig(ap_index, mfp);
13684
13685 memset(&params, 0, sizeof(params));
13686 params.name = "transition_disable";
13687 if (security->wpa3_transition_disable == TRUE)
13688 params.value = "0x01";
13689 else
13690 params.value = "0x00";
13691 wifi_hostapdWrite(config_file, &params, 1);
13692
13693 memset(&params, 0, sizeof(params));
13694 params.name = "wpa_group_rekey";
13695 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13696 params.value = buf;
13697 wifi_hostapdWrite(config_file, &params, 1);
13698
13699 memset(&params, 0, sizeof(params));
13700 params.name = "wpa_strict_rekey";
13701 params.value = security->strict_rekey?"1":"0";
13702 wifi_hostapdWrite(config_file, &params, 1);
13703
13704 memset(&params, 0, sizeof(params));
13705 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013706 if (security->eapol_key_retries == 0)
13707 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013708 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13709 params.value = buf;
13710 wifi_hostapdWrite(config_file, &params, 1);
13711
13712 memset(&params, 0, sizeof(params));
13713 params.name = "disable_pmksa_caching";
13714 params.value = security->disable_pmksa_caching?"1":"0";
13715 wifi_hostapdWrite(config_file, &params, 1);
13716
developer23e71282023-01-18 10:25:19 +080013717 if (multiple_set == FALSE) {
13718 wifi_setApEnable(ap_index, FALSE);
13719 wifi_setApEnable(ap_index, TRUE);
13720 }
developer587c1b62022-09-27 15:58:59 +080013721
13722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13723
developer06a01d92022-09-07 16:32:39 +080013724 return RETURN_OK;
13725}
13726
13727INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13728{
developer9df4e652022-10-11 11:27:38 +080013729 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013730 char config_file[128] = {0};
13731 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013732 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013733
13734 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13735 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13736 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13737 security->mode = wifi_security_mode_none;
13738 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013739 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013740 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013741 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013742 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013743 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013744 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013745 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013746 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013747 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013748 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013749 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013750 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013751 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013752 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013753 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013754 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013755 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013756 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013757 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013758 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013759 }
13760
13761 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13762 if (security->mode == wifi_security_mode_none)
13763 security->encr = wifi_encryption_none;
13764 else {
13765 if (strcmp(buf, "TKIP") == 0)
13766 security->encr = wifi_encryption_tkip;
13767 else if (strcmp(buf, "CCMP") == 0)
13768 security->encr = wifi_encryption_aes;
13769 else
13770 security->encr = wifi_encryption_aes_tkip;
13771 }
13772
developer9df4e652022-10-11 11:27:38 +080013773 if (security->mode != wifi_encryption_none) {
13774 memset(buf, 0, sizeof(buf));
13775 // wpa3 can use one or both configs as password, so we check sae_password first.
13776 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013777 if (strlen(buf) != 0) {
13778 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13779 security->u.key.type = wifi_security_key_type_sae;
13780 set_sae = TRUE;
13781 strncpy(security->u.key.key, buf, sizeof(buf));
13782 }
13783 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13784 if (strlen(buf) != 0){
13785 if (set_sae == TRUE)
13786 security->u.key.type = wifi_security_key_type_psk_sae;
13787 else if (strlen(buf) == 64)
13788 security->u.key.type = wifi_security_key_type_psk;
13789 else
13790 security->u.key.type = wifi_security_key_type_pass;
13791 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013792 }
developer9df4e652022-10-11 11:27:38 +080013793 security->u.key.key[255] = '\0';
13794 }
13795
developer587c1b62022-09-27 15:58:59 +080013796 memset(buf, 0, sizeof(buf));
13797 wifi_getApSecurityMFPConfig(ap_index, buf);
13798 if (strcmp(buf, "Disabled") == 0)
13799 security->mfp = wifi_mfp_cfg_disabled;
13800 else if (strcmp(buf, "Optional") == 0)
13801 security->mfp = wifi_mfp_cfg_optional;
13802 else if (strcmp(buf, "Required") == 0)
13803 security->mfp = wifi_mfp_cfg_required;
13804
13805 memset(buf, 0, sizeof(buf));
13806 security->wpa3_transition_disable = FALSE;
13807 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13808 disable = strtol(buf, NULL, 16);
13809 if (disable != 0)
13810 security->wpa3_transition_disable = TRUE;
13811
13812 memset(buf, 0, sizeof(buf));
13813 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13814 if (strlen(buf) == 0)
13815 security->rekey_interval = 86400;
13816 else
13817 security->rekey_interval = strtol(buf, NULL, 10);
13818
13819 memset(buf, 0, sizeof(buf));
13820 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13821 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013822 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013823 else
13824 security->strict_rekey = strtol(buf, NULL, 10);
13825
13826 memset(buf, 0, sizeof(buf));
13827 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13828 if (strlen(buf) == 0)
13829 security->eapol_key_retries = 4;
13830 else
13831 security->eapol_key_retries = strtol(buf, NULL, 10);
13832
13833 memset(buf, 0, sizeof(buf));
13834 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13835 if (strlen(buf) == 0)
13836 security->disable_pmksa_caching = FALSE;
13837 else
13838 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13839
13840 /* TODO
13841 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13842 */
13843 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13844 security->eap_identity_req_timeout = 0;
13845 security->eap_identity_req_retries = 0;
13846 security->eap_req_timeout = 0;
13847 security->eap_req_retries = 0;
13848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013849 return RETURN_OK;
13850}
13851
13852#endif /* WIFI_HAL_VERSION_3 */
13853
13854#ifdef WIFI_HAL_VERSION_3_PHASE2
13855INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13856{
developerd946fd62022-12-08 18:03:28 +080013857 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013858 char cmd[128] = {0};
13859 char buf[128] = {0};
13860 char *mac_addr = NULL;
13861 BOOL status = FALSE;
13862 size_t len = 0;
13863
13864 if(ap_index > MAX_APS)
13865 return RETURN_ERR;
13866
13867 *output_numDevices = 0;
13868 wifi_getApEnable(ap_index, &status);
13869 if (status == FALSE)
13870 return RETURN_OK;
13871
developerac6f1142022-12-20 19:26:35 +080013872 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013873 return RETURN_ERR;
13874 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013875 _syscmd(cmd, buf, sizeof(buf));
13876
13877 mac_addr = strtok(buf, "\n");
13878 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13879 *output_numDevices = i + 1;
13880 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13881 addr_ptr = output_deviceMacAddressArray[i];
13882 mac_addr_aton(addr_ptr, mac_addr);
13883 mac_addr = strtok(NULL, "\n");
13884 }
13885
13886 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013887}
13888#else
13889INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13890{
developerd946fd62022-12-08 18:03:28 +080013891 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013892 char cmd[128];
13893 BOOL status = false;
13894
13895 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13896 return RETURN_ERR;
13897
13898 output_buf[0] = '\0';
13899
13900 wifi_getApEnable(ap_index,&status);
13901 if (!status)
13902 return RETURN_OK;
13903
developerac6f1142022-12-20 19:26:35 +080013904 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013905 return RETURN_ERR;
13906 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013907 _syscmd(cmd, output_buf, output_buf_size);
13908
13909 return RETURN_OK;
13910}
13911#endif
developer2f513ab2022-09-13 14:26:06 +080013912
13913INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13914{
13915 char output[16]={'\0'};
13916 char config_file[MAX_BUF_SIZE] = {0};
13917
13918 if (!enable)
13919 return RETURN_ERR;
13920
13921 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13922 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13923
13924 if (strlen(output) == 0)
13925 *enable = FALSE;
13926 else if (strncmp(output, "1", 1) == 0)
13927 *enable = TRUE;
13928 else
13929 *enable = FALSE;
13930
13931 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13932 return RETURN_OK;
13933}
developer2d9c30f2022-09-13 15:06:14 +080013934
13935INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13936{
developer804c64f2022-10-19 13:54:40 +080013937 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013938 return RETURN_ERR;
13939 *output_enable=TRUE;
13940 return RETURN_OK;
13941}
developerfd7d2892022-09-13 16:44:53 +080013942
13943INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13944{
13945 char cmd[128] = {0};
13946 char buf[128] = {0};
13947 char line[128] = {0};
13948 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013949 FILE *f = NULL;
13950 int index = 0;
13951 int exp = 0;
13952 int mantissa = 0;
13953 int duration = 0;
13954 int radio_index = 0;
13955 int max_radio_num = 0;
13956 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013957 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013958 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13959
13960 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013961
developerfd7d2892022-09-13 16:44:53 +080013962 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013963
13964 phyId = radio_index_to_phy(radio_index);
developer439baa32024-05-02 15:54:58 +080013965 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", single_wiphy ? radio_index : phyId);
developerfd7d2892022-09-13 16:44:53 +080013966 _syscmd(cmd, buf, sizeof(buf));
13967 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13968 if (*numSessionReturned > maxNumberSessions)
13969 *numSessionReturned = maxNumberSessions;
13970 else if (*numSessionReturned < 1) {
13971 *numSessionReturned = 0;
13972 return RETURN_OK;
13973 }
13974
developer439baa32024-05-02 15:54:58 +080013975 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", single_wiphy ? radio_index : phyId, *numSessionReturned);
developerfd7d2892022-09-13 16:44:53 +080013976 if ((f = popen(cmd, "r")) == NULL) {
13977 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13978 return RETURN_ERR;
13979 }
13980
13981 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013982 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013983 char *tmp = NULL;
13984 strcpy(buf, line);
13985 tmp = strtok(buf, " ");
13986 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13987 tmp = strtok(NULL, " ");
13988 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13989 tmp = strtok(NULL, " ");
13990 if (strstr(tmp, "t")) {
13991 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13992 }
13993 if (strstr(tmp, "a")) {
13994 twtSessions[index].twtParameters.operation.announced = TRUE;
13995 }
13996 tmp = strtok(NULL, " ");
13997 exp = strtol(tmp, NULL, 10);
13998 tmp = strtok(NULL, " ");
13999 mantissa = strtol(tmp, NULL, 10);
14000 tmp = strtok(NULL, " ");
14001 duration = strtol(tmp, NULL, 10);
14002
14003 // only implicit supported
14004 twtSessions[index].twtParameters.operation.implicit = TRUE;
14005 // only individual agreement supported
14006 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
14007
14008 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
14009 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080014010 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080014011 // Overflow handling
14012 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
14013 } else {
14014 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
14015 }
14016 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
14017 index++;
14018 }
14019
14020 pclose(f);
14021 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14022 return RETURN_OK;
14023}