blob: 62b986f17b151dd6b7d5a24bd7f0023ab1575b4b [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
138static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
139 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
140 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
141 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
142 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
143 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
144 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
145 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
146 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
148 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
149 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
150 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
151 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
152 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
153 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
154 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
155};
156
157typedef unsigned long long u64;
158
159/* Enum to define WiFi Bands */
160typedef enum
161{
162 band_invalid = -1,
163 band_2_4 = 0,
164 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800165 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800166} wifi_band;
167
developerdb744382022-09-13 15:34:54 +0800168typedef enum {
169 WIFI_MODE_A = 0x01,
170 WIFI_MODE_B = 0x02,
171 WIFI_MODE_G = 0x04,
172 WIFI_MODE_N = 0x08,
173 WIFI_MODE_AC = 0x10,
174 WIFI_MODE_AX = 0x20,
developer7c4cd202023-03-01 10:56:29 +0800175 WIFI_MODE_BE = 0x40,
developerdb744382022-09-13 15:34:54 +0800176} wifi_ieee80211_Mode;
177
developer06a01d92022-09-07 16:32:39 +0800178#ifdef WIFI_HAL_VERSION_3
179
180// Return number of elements in array
181#ifndef ARRAY_SIZE
182#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
183#endif /* ARRAY_SIZE */
184
185#ifndef ARRAY_AND_SIZE
186#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
187#endif /* ARRAY_AND_SIZE */
188
189#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
190
191typedef struct {
192 int32_t value;
193 int32_t param;
194 intptr_t key;
195 intptr_t data;
196} wifi_secur_list;
197
developerfa41b1f2023-01-06 10:25:51 +0800198static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
199static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
developer72ec5572023-01-05 16:27:13 +0800200static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer06a01d92022-09-07 16:32:39 +0800201wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
202wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
203char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800204static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800205
206static wifi_secur_list map_security[] =
207{
208 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
209 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
210 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800216 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800218 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800219 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800220};
221
developerefb790a2023-12-26 18:58:32 +0800222typedef struct {
223 char ssid[MAX_BUF_SIZE];
224 char wpa[MAX_BUF_SIZE];
225 char wpa_key_mgmt[MAX_BUF_SIZE];
226 char wpa_passphrase[MAX_BUF_SIZE];
227 char ap_isolate[MAX_BUF_SIZE];
228 char macaddr_acl[MAX_BUF_SIZE];
229 char bss_transition[MAX_BUF_SIZE];
230 char ignore_broadcast_ssid[MAX_BUF_SIZE];
231 char max_sta[MAX_BUF_SIZE];
232} __attribute__((packed)) wifi_vap_cfg_t;
233
234pthread_t pthread_id;
235int result = 0, tflag = 0;
236wifi_vap_cfg_t vap_info[MAX_NUM_RADIOS*MAX_NUM_VAP_PER_RADIO];
237int syn_flag = 0;
238
developer06a01d92022-09-07 16:32:39 +0800239wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
240{
241 wifi_secur_list *item;
242 int i;
243
244 for (item = list,i = 0;i < list_sz; item++, i++) {
245 if ((int)(item->key) == key) {
246 return item;
247 }
248 }
249
250 return NULL;
251}
252
253char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
254{
255 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
256
257 if (!item) {
258 return "";
259 }
260
261 return (char *)(item->data);
262}
263
264wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
265{
266 wifi_secur_list *item;
267 int i;
268
269 for (item = list,i = 0;i < list_sz; item++, i++) {
270 if (strcmp((char *)(item->data), str) == 0) {
271 return item;
272 }
273 }
274
275 return NULL;
276}
277#endif /* WIFI_HAL_VERSION_3 */
278
279#ifdef HAL_NETLINK_IMPL
280typedef struct {
281 int id;
282 struct nl_sock* socket;
283 struct nl_cb* cb;
284} Netlink;
285
286static int mac_addr_aton(unsigned char *mac_addr, char *arg)
287{
288 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800289 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 +0800290 mac_addr[0] = mac_addr_int[0];
291 mac_addr[1] = mac_addr_int[1];
292 mac_addr[2] = mac_addr_int[2];
293 mac_addr[3] = mac_addr_int[3];
294 mac_addr[4] = mac_addr_int[4];
295 mac_addr[5] = mac_addr_int[5];
296 return 0;
297}
298
299static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
300{
301 unsigned int mac_addr_int[6]={};
302 mac_addr_int[0] = arg[0];
303 mac_addr_int[1] = arg[1];
304 mac_addr_int[2] = arg[2];
305 mac_addr_int[3] = arg[3];
306 mac_addr_int[4] = arg[4];
307 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800308 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 +0800309 return;
310}
311
312static int ieee80211_frequency_to_channel(int freq)
313{
developerf5745ee2022-10-05 16:09:53 +0800314 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800315 if (freq == 2484)
316 return 14;
developerf5745ee2022-10-05 16:09:53 +0800317 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
318 else if (freq == 5935)
319 return 2;
developer06a01d92022-09-07 16:32:39 +0800320 else if (freq < 2484)
321 return (freq - 2407) / 5;
322 else if (freq >= 4910 && freq <= 4980)
323 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800324 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800325 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800326 else if (freq <= 45000) /* DMG band lower limit */
327 /* see 802.11ax D6.1 27.3.23.2 */
328 return (freq - 5950) / 5;
329 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800330 return (freq - 56160) / 2160;
331 else
332 return 0;
333}
334
335static int initSock80211(Netlink* nl) {
336 nl->socket = nl_socket_alloc();
337 if (!nl->socket) {
338 fprintf(stderr, "Failing to allocate the sock\n");
339 return -ENOMEM;
340 }
341
342 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
343
344 if (genl_connect(nl->socket)) {
345 fprintf(stderr, "Failed to connect\n");
346 nl_close(nl->socket);
347 nl_socket_free(nl->socket);
348 return -ENOLINK;
349 }
350
351 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
352 if (nl->id< 0) {
353 fprintf(stderr, "interface not found.\n");
354 nl_close(nl->socket);
355 nl_socket_free(nl->socket);
356 return -ENOENT;
357 }
358
359 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
360 if ((!nl->cb)) {
361 fprintf(stderr, "Failed to allocate netlink callback.\n");
362 nl_close(nl->socket);
363 nl_socket_free(nl->socket);
364 return ENOMEM;
365 }
366
367 return nl->id;
368}
369
370static int nlfree(Netlink *nl)
371{
372 nl_cb_put(nl->cb);
373 nl_close(nl->socket);
374 nl_socket_free(nl->socket);
375 return 0;
376}
377
378static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
379 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
380 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
381 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
382};
383
384static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
385};
386
387static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
388};
389
390typedef struct _wifi_channelStats_loc {
391 INT array_size;
392 INT ch_number;
393 BOOL ch_in_pool;
394 INT ch_noise;
395 BOOL ch_radar_noise;
396 INT ch_max_80211_rssi;
397 INT ch_non_80211_noise;
398 INT ch_utilization;
399 ULLONG ch_utilization_total;
400 ULLONG ch_utilization_busy;
401 ULLONG ch_utilization_busy_tx;
402 ULLONG ch_utilization_busy_rx;
403 ULLONG ch_utilization_busy_self;
404 ULLONG ch_utilization_busy_ext;
405} wifi_channelStats_t_loc;
406
407typedef struct wifi_device_info {
408 INT wifi_devIndex;
409 UCHAR wifi_devMacAddress[6];
410 CHAR wifi_devIPAddress[64];
411 BOOL wifi_devAssociatedDeviceAuthentiationState;
412 INT wifi_devSignalStrength;
413 INT wifi_devTxRate;
414 INT wifi_devRxRate;
415} wifi_device_info_t;
416
417#endif
418
419//For 5g Alias Interfaces
420static BOOL priv_flag = TRUE;
421static BOOL pub_flag = TRUE;
422static BOOL Radio_flag = TRUE;
423//wifi_setApBeaconRate(1, beaconRate);
424
developer1e5aa162022-09-13 16:06:24 +0800425BOOL multiple_set = FALSE;
426
developer06a01d92022-09-07 16:32:39 +0800427struct params
428{
429 char * name;
430 char * value;
431};
432
433static int _syscmd(char *cmd, char *retBuf, int retBufSize)
434{
435 FILE *f;
436 char *ptr = retBuf;
437 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
438
439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
440 if((f = popen(cmd, "r")) == NULL) {
441 fprintf(stderr,"\npopen %s error\n", cmd);
442 return RETURN_ERR;
443 }
444
445 while(!feof(f))
446 {
447 *ptr = 0;
448 if(bufSize>=128) {
449 bufbytes=128;
450 } else {
451 bufbytes=bufSize-1;
452 }
453
454 fgets(ptr,bufbytes,f);
455 readbytes=strlen(ptr);
456
457 if(!readbytes)
458 break;
459
460 bufSize-=readbytes;
461 ptr += readbytes;
462 }
463 cmd_ret = pclose(f);
464 retBuf[retBufSize-1]=0;
465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
466
467 return cmd_ret >> 8;
468}
469
developer033b37b2022-10-18 11:27:46 +0800470INT radio_index_to_phy(int radioIndex)
471{
472 char cmd[128] = {0};
473 char buf[64] = {0};
474 int phyIndex = 0;
475 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
476 _syscmd(cmd, buf, sizeof(buf));
477
478 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800479 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800480 return RETURN_ERR;
481 }
482 sscanf(buf, "phy%d", &phyIndex);
483
484 return phyIndex;
485}
developer026ac9e2022-11-07 13:46:24 +0800486
developer431128d2022-12-16 15:30:41 +0800487INT wifi_getMaxRadioNumber(INT *max_radio_num)
488{
489 char cmd[64] = {0};
490 char buf[4] = {0};
491
492 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
493
494 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
495 _syscmd(cmd, buf, sizeof(buf));
496 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
497
498 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
499
500 return RETURN_OK;
501}
502
developer59ff6de2023-02-08 17:58:14 +0800503static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
504{
505 char cmd[MAX_CMD_SIZE]={'\0'};
506 char buf[MAX_BUF_SIZE]={'\0'};
507 int ret = 0;
508
509 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
510 ret = _syscmd(cmd, buf, sizeof(buf));
511 if ((ret != 0) && (strlen(buf) == 0))
512 return -1;
513 snprintf(output, output_size, "%s", buf);
514
515 return 0;
516}
517
518static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
519{
520 char cmd[MAX_CMD_SIZE]={'\0'};
521 char buf[MAX_BUF_SIZE]={'\0'};
522
523 for(int i=0;i<item_count;i++)
524 {
525 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
526 if (strlen(buf) == 0) //Insert
527 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
528 else //Update
529 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
530
531 if(_syscmd(cmd, buf, sizeof(buf)))
532 return -1;
533 }
534
535 return 0;
536}
537
developer431128d2022-12-16 15:30:41 +0800538wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800539{
540 char cmd[128] = {0};
541 char buf[64] = {0};
developer59ff6de2023-02-08 17:58:14 +0800542 char config_file[128] = {0};
developer026ac9e2022-11-07 13:46:24 +0800543 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800544 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800545 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800546 int radioIndex = 0;
547 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800548 wifi_band band = band_invalid;
549
550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800551
developer431128d2022-12-16 15:30:41 +0800552 wifi_getMaxRadioNumber(&max_radio_num);
553 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800554 phyIndex = radio_index_to_phy(radioIndex);
developer59ff6de2023-02-08 17:58:14 +0800555 snprintf(cmd, sizeof(cmd), "cat /sys/class/ieee80211/phy%d/device/device 2> /dev/null", phyIndex);
556 _syscmd(cmd, buf, sizeof(buf));
557 if (strncmp(buf, "0x7915", 6) == 0) { // harrier have two bands, consider as a special case.
558 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
559 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
560 if (strncmp(buf, "a", 1) == 0)
561 return band_5;
562 else
563 return band_2_4;
564 }
developer5884e982022-10-06 10:52:50 +0800565 while(i < 10){
developer59ff6de2023-02-08 17:58:14 +0800566 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tr -d ':\\n' | awk '{print $2}'", phyIndex);
developer5884e982022-10-06 10:52:50 +0800567 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800568 nl80211_band = strtol(buf, NULL, 10);
569 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800570 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800571 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800572 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800573 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800574 band = band_6;
575
576 if(band != band_invalid)
577 break;
578
579 i++;
580 sleep(1);
581 }
developerc707e972022-09-13 15:38:02 +0800582
583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
584 return band;
585}
586
developerd946fd62022-12-08 18:03:28 +0800587//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800588static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800589{
590 char config_file[128] = {0};
591
592 if (interface_name == NULL)
593 return RETURN_ERR;
594
595 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerefb790a2023-12-26 18:58:32 +0800596#ifdef DYNAMIC_IF_NAME
developerd946fd62022-12-08 18:03:28 +0800597 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
598 wifi_hostapdRead(config_file, "interface", interface_name, 16);
599 if (strlen(interface_name) == 0)
600 return RETURN_ERR;
developerefb790a2023-12-26 18:58:32 +0800601#else
602 sprintf(interface_name, "%s%d",AP_PREFIX, apIndex);
603#endif
developerd946fd62022-12-08 18:03:28 +0800604 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
605 return RETURN_OK;
606}
607
developerac6f1142022-12-20 19:26:35 +0800608// wifi agent will call this function, do not change the parameter
609void GetInterfaceName(char *interface_name, char *conf_file)
610{
611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
612 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
613 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
614}
615
developer06a01d92022-09-07 16:32:39 +0800616static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
617{
developerd946fd62022-12-08 18:03:28 +0800618 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800619 if (multiple_set == TRUE)
620 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800621 char cmd[MAX_CMD_SIZE]="", output[32]="";
622 FILE *fp;
623 int i;
624 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800625 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800626 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800627 for(i=0; i<item_count; i++, list++)
628 {
developerd946fd62022-12-08 18:03:28 +0800629 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800630 if((fp = popen(cmd, "r"))==NULL)
631 {
632 perror("popen failed");
633 return -1;
634 }
635 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
636 {
637 pclose(fp);
638 perror("fgets failed");
639 return -1;
640 }
641 pclose(fp);
642 }
643 return 0;
644}
645
646static int wifi_reloadAp(int apIndex)
647{
developerd946fd62022-12-08 18:03:28 +0800648 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800649 if (multiple_set == TRUE)
650 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800651 char cmd[MAX_CMD_SIZE]="";
652 char buf[MAX_BUF_SIZE]="";
653
developerac6f1142022-12-20 19:26:35 +0800654 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800655 return RETURN_ERR;
656 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800657 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
658 return RETURN_ERR;
659
developerd946fd62022-12-08 18:03:28 +0800660 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800661 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
662 return RETURN_ERR;
663
developerd946fd62022-12-08 18:03:28 +0800664 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800665 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
666 return RETURN_ERR;
667
668 return RETURN_OK;
669}
670
developer06a01d92022-09-07 16:32:39 +0800671INT File_Reading(CHAR *file, char *Value)
672{
673 FILE *fp = NULL;
674 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
675 int count = 0;
676
677 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
678 fp = popen(file,"r");
679 if(fp == NULL)
680 return RETURN_ERR;
681
682 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
683 {
684 for(count=0;buf[count]!='\n';count++)
685 copy_buf[count]=buf[count];
686 copy_buf[count]='\0';
687 }
688 strcpy(Value,copy_buf);
689 pclose(fp);
690 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
691
692 return RETURN_OK;
693}
694
695void wifi_RestartHostapd_2G()
696{
697 int Public2GApIndex = 4;
698
699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
700 wifi_setApEnable(Public2GApIndex, FALSE);
701 wifi_setApEnable(Public2GApIndex, TRUE);
702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
703}
704
705void wifi_RestartHostapd_5G()
706{
707 int Public5GApIndex = 5;
708
709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
710 wifi_setApEnable(Public5GApIndex, FALSE);
711 wifi_setApEnable(Public5GApIndex, TRUE);
712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
713}
714
715void wifi_RestartPrivateWifi_2G()
716{
717 int PrivateApIndex = 0;
718
719 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
720 wifi_setApEnable(PrivateApIndex, FALSE);
721 wifi_setApEnable(PrivateApIndex, TRUE);
722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
723}
724
725void wifi_RestartPrivateWifi_5G()
726{
727 int Private5GApIndex = 1;
728
729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
730 wifi_setApEnable(Private5GApIndex, FALSE);
731 wifi_setApEnable(Private5GApIndex, TRUE);
732 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
733}
734
735static int writeBandWidth(int radioIndex,char *bw_value)
736{
737 char buf[MAX_BUF_SIZE];
738 char cmd[MAX_CMD_SIZE];
739
740 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
741 if(_syscmd(cmd, buf, sizeof(buf)))
742 {
743 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
744 _syscmd(cmd, buf, sizeof(buf));
745 return RETURN_OK;
746 }
747
748 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
749 _syscmd(cmd,buf,sizeof(buf));
750 return RETURN_OK;
751}
752
753static int readBandWidth(int radioIndex,char *bw_value)
754{
developer30423732022-12-01 16:17:49 +0800755 char buf[MAX_BUF_SIZE] = {0};
756 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800757 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
758 _syscmd(cmd,buf,sizeof(buf));
759 if(NULL!=strstr(buf,"20MHz"))
developer06a01d92022-09-07 16:32:39 +0800760 strcpy(bw_value,"20MHz");
developer06a01d92022-09-07 16:32:39 +0800761 else if(NULL!=strstr(buf,"40MHz"))
developer06a01d92022-09-07 16:32:39 +0800762 strcpy(bw_value,"40MHz");
developer06a01d92022-09-07 16:32:39 +0800763 else if(NULL!=strstr(buf,"80MHz"))
developer06a01d92022-09-07 16:32:39 +0800764 strcpy(bw_value,"80MHz");
developer57fa24a2023-03-15 17:25:07 +0800765 else if(NULL!=strstr(buf,"160MHz"))
766 strcpy(bw_value,"160MHz");
767 else if(NULL!=strstr(buf,"320MHz"))
768 strcpy(bw_value,"320MHz");
developer06a01d92022-09-07 16:32:39 +0800769 else
developer06a01d92022-09-07 16:32:39 +0800770 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800771 return RETURN_OK;
772}
773
developer264159b2022-11-02 09:41:35 +0800774// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800775INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
776{
developer5f222492022-09-13 15:21:52 +0800777 struct params params={'\0'};
778 char config_file[MAX_BUF_SIZE] = {0};
779 char buf[MAX_BUF_SIZE] = {'\0'};
780
781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800782 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800783 if (strlen (beaconRate) >= 5) {
784 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
785 buf[strlen(beaconRate) - 4] = '\0';
786 } else if (strlen(beaconRate) > 0)
787 strcpy(buf, beaconRate);
788 else
789 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800790
791 params.name = "beacon_rate";
792 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
793 if (strncmp(buf, "5.5", 3) == 0) {
794 snprintf(buf, sizeof(buf), "55");
795 params.value = buf;
796 } else {
797 strcat(buf, "0");
798 params.value = buf;
799 }
800
801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
802 wifi_hostapdWrite(config_file, &params, 1);
803 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
804 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
805
806 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800807}
808
809INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
810{
developer1d57d002022-10-12 18:03:15 +0800811 char config_file[128] = {'\0'};
812 char temp_output[128] = {'\0'};
813 char buf[128] = {'\0'};
814 char cmd[128] = {'\0'};
815 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800816 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800817
818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
819 if (NULL == beaconRate)
820 return RETURN_ERR;
821
822 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
823 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800824 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800825 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
826 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800827 if (strncmp(buf, "55", 2) == 0)
828 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
829 else {
830 rate = strtol(buf, NULL, 10)/10;
831 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
832 }
developer5f222492022-09-13 15:21:52 +0800833 } else {
developer1d57d002022-10-12 18:03:15 +0800834 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800835 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 +0800836 _syscmd(cmd, buf, sizeof(buf));
837 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800838 }
839 strncpy(beaconRate, temp_output, sizeof(temp_output));
840 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
841
842 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800843}
844
845INT wifi_setLED(INT radioIndex, BOOL enable)
846{
847 return 0;
848}
849INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
850{
851 return RETURN_OK;
852}
853/**********************************************************************************
854 *
855 * Wifi Subsystem level function prototypes
856 *
857**********************************************************************************/
858//---------------------------------------------------------------------------------------------------
859//Wifi system api
860//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
861INT wifi_getHalVersion(CHAR *output_string) //RDKB
862{
863 if(!output_string)
864 return RETURN_ERR;
865 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
866
867 return RETURN_OK;
868}
869
870
871/* wifi_factoryReset() function */
872/**
873* @description Clears internal variables to implement a factory reset of the Wi-Fi
874* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
875*
876* @param None
877*
878* @return The status of the operation.
879* @retval RETURN_OK if successful.
880* @retval RETURN_ERR if any error is detected
881*
882* @execution Synchronous
883* @sideeffect None
884*
885* @note This function must not suspend and must not invoke any blocking system
886* calls. It should probably just send a message to a driver event handler task.
887*
888*/
889INT wifi_factoryReset()
890{
891 char cmd[128];
892
893 /*delete running hostapd conf files*/
developer72ec5572023-01-05 16:27:13 +0800894 wifi_dbg_printf("\n[%s]: deleting hostapd conf file",__func__);
895 sprintf(cmd, "rm -rf /nvram/hostapd*");
developer06a01d92022-09-07 16:32:39 +0800896 system(cmd);
897 system("systemctl restart hostapd.service");
898
899 return RETURN_OK;
900}
901
902/* wifi_factoryResetRadios() function */
903/**
904* @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.
905*
906* @param None
907* @return The status of the operation
908* @retval RETURN_OK if successful
909* @retval RETURN_ERR if any error is detected
910*
911* @execution Synchronous
912*
913* @sideeffect None
914*
915* @note This function must not suspend and must not invoke any blocking system
916* calls. It should probably just send a message to a driver event handler task.
917*
918*/
919INT wifi_factoryResetRadios()
920{
developer72ec5572023-01-05 16:27:13 +0800921 int max_radio_num = 0;
922 wifi_getMaxRadioNumber(&max_radio_num);
923 for (int radioIndex = 0; radioIndex < max_radio_num; radioIndex++)
924 wifi_factoryResetRadio(radioIndex);
developer06a01d92022-09-07 16:32:39 +0800925
developer72ec5572023-01-05 16:27:13 +0800926 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800927}
928
929
930/* wifi_factoryResetRadio() function */
931/**
932* @description Restore selected radio parameters without touching access point parameters
933*
934* @param radioIndex - Index of Wi-Fi Radio channel
935*
936* @return The status of the operation.
937* @retval RETURN_OK if successful.
938* @retval RETURN_ERR if any error is detected
939*
940* @execution Synchronous.
941* @sideeffect None.
942*
943* @note This function must not suspend and must not invoke any blocking system
944* calls. It should probably just send a message to a driver event handler task.
945*
946*/
947INT wifi_factoryResetRadio(int radioIndex) //RDKB
948{
developer72ec5572023-01-05 16:27:13 +0800949 char cmd[128] = {0};
950 char buf[128] = {0};
951 int max_radio_num = 0;
952
953 wifi_getMaxRadioNumber(&max_radio_num);
954 if (radioIndex < 0 || radioIndex > max_radio_num)
955 return RETURN_ERR;
956
957 snprintf(cmd, sizeof(cmd), "systemctl stop hostapd.service");
958 _syscmd(cmd, buf, sizeof(buf));
developer5ff7f5f2022-09-13 15:12:16 +0800959
developer06a01d92022-09-07 16:32:39 +0800960 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72ec5572023-01-05 16:27:13 +0800961 snprintf(cmd, sizeof(cmd), "rm /nvram/hostapd%d* %s%d.txt", radioIndex, GUARD_INTERVAL_FILE, radioIndex);
962 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800963
developer72ec5572023-01-05 16:27:13 +0800964 snprintf(cmd, sizeof(cmd), "systemctl start hostapd.service");
965 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800966 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
967 return RETURN_OK;
968}
969
970/* wifi_initRadio() function */
971/**
972* Description: This function call initializes the specified radio.
973* Implementation specifics may dictate the functionality since
974* different hardware implementations may have different initilization requirements.
975* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
976*
977* @return The status of the operation.
978* @retval RETURN_OK if successful.
979* @retval RETURN_ERR if any error is detected
980*
981* @execution Synchronous.
982* @sideeffect None.
983*
984* @note This function must not suspend and must not invoke any blocking system
985* calls. It should probably just send a message to a driver event handler task.
986*
987*/
988INT wifi_initRadio(INT radioIndex)
989{
990 //TODO: Initializes the wifi subsystem (for specified radio)
991 return RETURN_OK;
992}
993void macfilter_init()
994{
995 char count[4]={'\0'};
996 char buf[253]={'\0'};
997 char tmp[19]={'\0'};
998 int dev_count,block,mac_entry=0;
999 char res[4]={'\0'};
1000 char acl_file_path[64] = {'\0'};
1001 FILE *fp = NULL;
1002 int index=0;
1003 char iface[10]={'\0'};
1004 char config_file[MAX_BUF_SIZE] = {0};
1005
1006
1007 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1008
1009 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +08001010 if (fp == NULL) {
1011 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
1012 return RETURN_ERR;
1013 }
developer06a01d92022-09-07 16:32:39 +08001014 sprintf(buf,"#!/bin/sh \n");
1015 fprintf(fp,"%s\n",buf);
1016
1017 system("chmod 0777 /tmp/mac_filter.sh");
1018
1019 for(index=0;index<=1;index++)
1020 {
1021 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1022 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1023 sprintf(buf,"syscfg get %dcountfilter",index);
1024 _syscmd(buf,count,sizeof(count));
1025 mac_entry=atoi(count);
1026
1027 sprintf(buf,"syscfg get %dblockall",index);
1028 _syscmd(buf,res,sizeof(res));
1029 block = atoi(res);
1030
1031 //Allow only those macs mentioned in ACL
1032 if(block==1)
1033 {
1034 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1035 fprintf(fp,"%s\n",buf);
1036 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1037 {
1038 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1039 _syscmd(buf,tmp,sizeof(tmp));
1040 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1041 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1042 fprintf(fp,"%s\n",buf);
1043 }
1044 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1045 fprintf(fp,"%s\n",buf);
1046 }
1047
1048 //Block all the macs mentioned in ACL
1049 else if(block==2)
1050 {
1051 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1052 fprintf(fp,"%s\n",buf);
1053
1054 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1055 {
1056 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1057 _syscmd(buf,tmp,sizeof(tmp));
1058 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1059 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1060 fprintf(fp,"%s\n",buf);
1061 }
1062 }
1063 }
1064 fclose(fp);
1065}
1066
1067// Initializes the wifi subsystem (all radios)
1068INT wifi_init() //RDKB
1069{
1070 char interface[MAX_BUF_SIZE]={'\0'};
1071 char bridge_name[MAX_BUF_SIZE]={'\0'};
1072 INT len=0;
1073
1074 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1075 //Not intitializing macfilter for Turris-Omnia Platform for now
1076 //macfilter_init();
1077
1078 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001079 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001080 sleep(2);//sleep to wait for hostapd to start
1081
1082 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1083
1084 return RETURN_OK;
1085}
1086
1087/* wifi_reset() function */
1088/**
1089* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1090* Implementation specifics may dictate what is actualy reset since
1091* different hardware implementations may have different requirements.
1092* Parameters : None
1093*
1094* @return The status of the operation.
1095* @retval RETURN_OK if successful.
1096* @retval RETURN_ERR if any error is detected
1097*
1098* @execution Synchronous.
1099* @sideeffect None.
1100*
1101* @note This function must not suspend and must not invoke any blocking system
1102* calls. It should probably just send a message to a driver event handler task.
1103*
1104*/
1105INT wifi_reset()
1106{
1107 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001108 system("systemctl stop hostapd.service");
1109 sleep(2);
1110 system("systemctl start hostapd.service");
1111 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001112 return RETURN_OK;
1113}
1114
1115/* wifi_down() function */
1116/**
1117* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1118* Implementation specifics may dictate some functionality since
1119* different hardware implementations may have different requirements.
1120*
1121* @param None
1122*
1123* @return The status of the operation
1124* @retval RETURN_OK if successful
1125* @retval RETURN_ERR if any error is detected
1126*
1127* @execution Synchronous
1128* @sideeffect None
1129*
1130* @note This function must not suspend and must not invoke any blocking system
1131* calls. It should probably just send a message to a driver event handler task.
1132*
1133*/
1134INT wifi_down()
1135{
1136 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer72ec5572023-01-05 16:27:13 +08001137 int max_num_radios = 0;
1138 wifi_getMaxRadioNumber(&max_num_radios);
1139 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1140 wifi_setRadioEnable(radioIndex, FALSE);
1141
developer06a01d92022-09-07 16:32:39 +08001142 return RETURN_OK;
1143}
1144
1145
1146/* wifi_createInitialConfigFiles() function */
1147/**
1148* @description This function creates wifi configuration files. The format
1149* and content of these files are implementation dependent. This function call is
1150* used to trigger this task if necessary. Some implementations may not need this
1151* function. If an implementation does not need to create config files the function call can
1152* do nothing and return RETURN_OK.
1153*
1154* @param None
1155*
1156* @return The status of the operation
1157* @retval RETURN_OK if successful
1158* @retval RETURN_ERR if any error is detected
1159*
1160* @execution Synchronous
1161* @sideeffect None
1162*
1163* @note This function must not suspend and must not invoke any blocking system
1164* calls. It should probably just send a message to a driver event handler task.
1165*
1166*/
1167INT wifi_createInitialConfigFiles()
1168{
1169 //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)
1170 return RETURN_OK;
1171}
1172
1173// outputs the country code to a max 64 character string
1174INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1175{
developerd946fd62022-12-08 18:03:28 +08001176 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001177 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001178 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001179 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001180
developerac6f1142022-12-20 19:26:35 +08001181 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001182 return RETURN_ERR;
1183 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001184 _syscmd(cmd, buf, sizeof(buf));
1185 if(strlen(buf) > 0)
1186 snprintf(output_string, 64, "%s", buf);
1187 else
1188 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001189
1190 return RETURN_OK;
1191}
1192
1193INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1194{
1195 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001196 char str[MAX_BUF_SIZE]={'\0'};
1197 char cmd[MAX_CMD_SIZE]={'\0'};
1198 struct params params;
1199 char config_file[MAX_BUF_SIZE] = {0};
1200
1201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1202 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1203 return RETURN_ERR;
1204
developerb86c6f32022-10-07 14:34:58 +08001205 if (strlen(CountryCode) == 0)
1206 strcpy(CountryCode, "US");
1207
developer7543b3b2022-09-13 13:47:17 +08001208 params.name = "country_code";
1209 params.value = CountryCode;
1210 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1211 int ret = wifi_hostapdWrite(config_file, &params, 1);
1212 if (ret) {
1213 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1214 ,__func__, ret);
1215 }
1216
1217 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1218 if (ret) {
1219 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1220 ,__func__, ret);
1221 }
developer7543b3b2022-09-13 13:47:17 +08001222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1223
developer06a01d92022-09-07 16:32:39 +08001224 return RETURN_OK;
1225}
1226
developera748dcf2022-09-13 15:56:48 +08001227INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1228{
developerd946fd62022-12-08 18:03:28 +08001229 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001230 char channel_util_file[64] = {0};
1231 char cmd[128] = {0};
1232 char buf[128] = {0};
1233 char line[128] = {0};
1234 char *param = NULL, *value = NULL;
1235 int read = 0;
1236 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1237 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1238 size_t len = 0;
1239 FILE *f = NULL;
1240
1241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1242
developerac6f1142022-12-20 19:26:35 +08001243 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001244 return RETURN_ERR;
1245 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001246 _syscmd(cmd, buf, sizeof(buf));
1247 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1248
1249 memset(cmd, 0, sizeof(cmd));
1250 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001251 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001252 if ((f = popen(cmd, "r")) == NULL) {
1253 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1254 return RETURN_ERR;
1255 }
1256
1257 read = getline(&line, &len, f);
1258 while (read != -1) {
1259 param = strtok(line, ":\t");
1260 value = strtok(NULL, " ");
1261 if(strstr(param, "frequency") != NULL) {
1262 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1263 }
1264 if(strstr(param, "noise") != NULL) {
1265 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1266 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1267 }
1268 if(strstr(param, "channel active time") != NULL) {
1269 ActiveTime = strtol(value, NULL, 10);
1270 }
1271 if(strstr(param, "channel busy time") != NULL) {
1272 BusyTime = strtol(value, NULL, 10);
1273 }
1274 if(strstr(param, "channel transmit time") != NULL) {
1275 TransmitTime = strtol(value, NULL, 10);
1276 }
1277 read = getline(&line, &len, f);
1278 }
1279 pclose(f);
1280
1281 // The file should store the last active, busy and transmit time
1282 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1283 f = fopen(channel_util_file, "r");
1284 if (f != NULL) {
1285 read = getline(&line, &len, f);
1286 preActiveTime = strtol(line, NULL, 10);
1287 read = getline(&line, &len, f);
1288 preBusyTime = strtol(line, NULL, 10);
1289 read = getline(&line, &len, f);
1290 preTransmitTime = strtol(line, NULL, 10);
1291 fclose(f);
1292 }
1293
1294 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1295 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1296
1297 f = fopen(channel_util_file, "w");
1298 if (f != NULL) {
1299 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1300 fclose(f);
1301 }
1302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1303 return RETURN_OK;
1304}
1305
developer06a01d92022-09-07 16:32:39 +08001306/**********************************************************************************
1307 *
1308 * Wifi radio level function prototypes
1309 *
1310**********************************************************************************/
1311
1312//Get the total number of radios in this wifi subsystem
1313INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1314{
1315 if (NULL == output)
1316 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001317 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001318
1319 return RETURN_OK;
1320}
1321
1322//Get the total number of SSID entries in this wifi subsystem
1323INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1324{
1325 if (NULL == output)
1326 return RETURN_ERR;
1327 *output = MAX_APS;
1328
1329 return RETURN_OK;
1330}
1331
1332//Get the Radio enable config parameter
1333INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1334{
developerd946fd62022-12-08 18:03:28 +08001335 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001336 char buf[128] = {0}, cmd[128] = {0};
developera77d84b2023-02-22 16:10:50 +08001337 int apIndex;
1338 int max_radio_num = 0;
developer06a01d92022-09-07 16:32:39 +08001339
1340 if (NULL == output_bool)
1341 return RETURN_ERR;
1342
1343 *output_bool = FALSE;
developera77d84b2023-02-22 16:10:50 +08001344
1345 wifi_getMaxRadioNumber(&max_radio_num);
1346
1347 if (radioIndex >= max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001348 return RETURN_ERR;
1349
developera77d84b2023-02-22 16:10:50 +08001350 /* loop all interface in radio, if any is enable, reture true, else return false */
1351 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1352 {
developer643b28f2023-04-04 10:26:01 +08001353 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developera77d84b2023-02-22 16:10:50 +08001354 continue;
1355 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1356 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001357
developera77d84b2023-02-22 16:10:50 +08001358 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 ||
1359 strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0) {
1360 /* return true if any interface is eanble */
1361 *output_bool = TRUE;
1362 break;
1363 }
1364 }
developer06a01d92022-09-07 16:32:39 +08001365 return RETURN_OK;
1366}
1367
1368INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1369{
developerd946fd62022-12-08 18:03:28 +08001370 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001371 char cmd[MAX_CMD_SIZE] = {0};
1372 char buf[MAX_CMD_SIZE] = {0};
1373 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001374 int max_radio_num = 0;
1375 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001376
1377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001378
1379 phyId = radio_index_to_phy(radioIndex);
1380
1381 wifi_getMaxRadioNumber(&max_radio_num);
1382
developer06a01d92022-09-07 16:32:39 +08001383 if(enable==FALSE)
1384 {
developera77d84b2023-02-22 16:10:50 +08001385 /* disable from max apindex to min, to avoid fail in mbss case */
1386 for(apIndex=(MAX_APS-max_radio_num+radioIndex); apIndex>=0; apIndex-=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001387 {
developer1e125222022-12-29 09:35:25 +08001388 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001389 continue;
developer1e125222022-12-29 09:35:25 +08001390
developer06a01d92022-09-07 16:32:39 +08001391 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001392 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001393 _syscmd(cmd, buf, sizeof(buf));
1394 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001395 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001396
developer2f18b9f2023-03-17 19:32:57 +08001397 if (!(apIndex/max_radio_num)) {
1398 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1399 _syscmd(cmd, buf, sizeof(buf));
1400 }
developer06a01d92022-09-07 16:32:39 +08001401 }
developer06a01d92022-09-07 16:32:39 +08001402 }
1403 else
1404 {
developer033b37b2022-10-18 11:27:46 +08001405 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001406 {
developer1e125222022-12-29 09:35:25 +08001407 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001408 continue;
developer1e125222022-12-29 09:35:25 +08001409
developer643b28f2023-04-04 10:26:01 +08001410 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001411 _syscmd(cmd, buf, sizeof(buf));
developera77d84b2023-02-22 16:10:50 +08001412 if(*buf == '1') {
developer2f18b9f2023-03-17 19:32:57 +08001413 if (!(apIndex/max_radio_num)) {
1414 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1415 ret = _syscmd(cmd, buf, sizeof(buf));
1416 if ( ret == RETURN_ERR) {
1417 fprintf(stderr, "VAP interface creation failed\n");
1418 continue;
1419 }
developera77d84b2023-02-22 16:10:50 +08001420 }
developer06a01d92022-09-07 16:32:39 +08001421 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001422 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001423 _syscmd(cmd, buf, sizeof(buf));
1424 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001425 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001426 }
1427 }
1428 }
1429
1430 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1431 return RETURN_OK;
1432}
1433
1434//Get the Radio enable status
1435INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1436{
1437 if (NULL == output_bool)
1438 return RETURN_ERR;
1439
1440 return wifi_getRadioEnable(radioIndex, output_bool);
1441}
1442
1443//Get the Radio Interface name from platform, eg "wlan0"
1444INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1445{
developer804c64f2022-10-19 13:54:40 +08001446 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001447 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001448 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001449}
1450
1451//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1452//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.
1453INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1454{
developerbcc556a2022-09-22 20:02:45 +08001455 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1456 // For max bit rate, we should always choose the best MCS
1457 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001458 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001459 char *tmp = NULL;
1460 UINT mode_map = 0;
1461 UINT num_subcarrier = 0;
1462 UINT code_bits = 0;
1463 float code_rate = 0; // use max code rate
1464 int NSS = 0;
1465 UINT Symbol_duration = 0;
1466 UINT GI_duration = 0;
1467 wifi_band band = band_invalid;
1468 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1469 BOOL enable = FALSE;
1470 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001471
1472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1473 if (NULL == output_string)
1474 return RETURN_ERR;
1475
developerbcc556a2022-09-22 20:02:45 +08001476 wifi_getRadioEnable(radioIndex, &enable);
1477 if (enable == FALSE) {
1478 snprintf(output_string, 64, "0 Mb/s");
1479 return RETURN_OK;
1480 }
1481
1482 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1483 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1484 return RETURN_ERR;
1485 }
1486
1487 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1488 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1489 return RETURN_ERR;
1490 }
1491
1492 if (gi == wifi_guard_interval_3200)
1493 GI_duration = 32;
1494 else if (gi == wifi_guard_interval_1600)
1495 GI_duration = 16;
1496 else if (gi == wifi_guard_interval_800)
1497 GI_duration = 8;
1498 else // auto, 400
1499 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001500
developerbcc556a2022-09-22 20:02:45 +08001501 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1502 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1503 return RETURN_ERR;
1504 }
1505
1506 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1507 strcpy(channel_bandwidth_str, "160");
1508
1509 if (mode_map & WIFI_MODE_AX) {
1510 if (strstr(channel_bandwidth_str, "160") != NULL)
1511 num_subcarrier = 1960;
1512 else if (strstr(channel_bandwidth_str, "80") != NULL)
1513 num_subcarrier = 980;
1514 else if (strstr(channel_bandwidth_str, "40") != NULL)
1515 num_subcarrier = 468;
1516 else if (strstr(channel_bandwidth_str, "20") != NULL)
1517 num_subcarrier = 234;
1518 code_bits = 10;
1519 code_rate = (float)5/6;
1520 Symbol_duration = 128;
1521 } else if (mode_map & WIFI_MODE_AC) {
1522 if (strstr(channel_bandwidth_str, "160") != NULL)
1523 num_subcarrier = 468;
1524 else if (strstr(channel_bandwidth_str, "80") != NULL)
1525 num_subcarrier = 234;
1526 else if (strstr(channel_bandwidth_str, "40") != NULL)
1527 num_subcarrier = 108;
1528 else if (strstr(channel_bandwidth_str, "20") != NULL)
1529 num_subcarrier = 52;
1530 code_bits = 8;
1531 code_rate = (float)5/6;
1532 Symbol_duration = 32;
1533 } else if (mode_map & WIFI_MODE_N) {
1534 if (strstr(channel_bandwidth_str, "160") != NULL)
1535 num_subcarrier = 468;
1536 else if (strstr(channel_bandwidth_str, "80") != NULL)
1537 num_subcarrier = 234;
1538 else if (strstr(channel_bandwidth_str, "40") != NULL)
1539 num_subcarrier = 108;
1540 else if (strstr(channel_bandwidth_str, "20") != NULL)
1541 num_subcarrier = 52;
1542 code_bits = 6;
1543 code_rate = (float)3/4;
1544 Symbol_duration = 32;
1545 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1546 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1547 snprintf(output_string, 64, "65 Mb/s");
1548 return RETURN_OK;
1549 } else {
1550 snprintf(output_string, 64, "0 Mb/s");
1551 return RETURN_OK;
1552 }
developer06a01d92022-09-07 16:32:39 +08001553
developerbcc556a2022-09-22 20:02:45 +08001554 // Spatial streams
1555 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1556 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1557 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001558 }
developerbcc556a2022-09-22 20:02:45 +08001559
1560 // multiple 10 is to align duration unit (0.1 us)
1561 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1562 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1563
developer06a01d92022-09-07 16:32:39 +08001564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1565
1566 return RETURN_OK;
1567}
1568#if 0
1569INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1570{
1571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1572 char cmd[64];
1573 char buf[1024];
1574 int apIndex;
1575
1576 if (NULL == output_string)
1577 return RETURN_ERR;
1578
1579 apIndex=(radioIndex==0)?0:1;
1580
developerd946fd62022-12-08 18:03:28 +08001581 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001582 _syscmd(cmd,buf, sizeof(buf));
1583
1584 snprintf(output_string, 64, "%s", buf);
1585 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1586 return RETURN_OK;
1587}
1588#endif
1589
1590
1591//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1592//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.
1593INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1594{
developer963da0c2022-09-13 15:58:27 +08001595 wifi_band band = band_invalid;
1596
developer06a01d92022-09-07 16:32:39 +08001597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1598 if (NULL == output_string)
1599 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001600
1601 band = wifi_index_to_band(radioIndex);
1602
1603 memset(output_string, 0, 10);
1604 if (band == band_2_4)
1605 strcpy(output_string, "2.4GHz");
1606 else if (band == band_5)
1607 strcpy(output_string, "5GHz");
1608 else if (band == band_6)
1609 strcpy(output_string, "6GHz");
1610 else
1611 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1613
1614 return RETURN_OK;
1615#if 0
1616 char buf[MAX_BUF_SIZE]={'\0'};
1617 char str[MAX_BUF_SIZE]={'\0'};
1618 char cmd[MAX_CMD_SIZE]={'\0'};
1619 char *ch=NULL;
1620 char *ch2=NULL;
1621
1622 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1623 if (NULL == output_string)
1624 return RETURN_ERR;
1625
1626
1627 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1628
1629 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1630 {
1631 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1632 return RETURN_ERR;
1633 }
1634 ch=strchr(buf,'\n');
1635 *ch='\0';
1636 ch=strchr(buf,'=');
1637 if(ch==NULL)
1638 return RETURN_ERR;
1639
1640
1641 ch++;
1642
1643 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1644 strcpy(buf,"0");
1645 if(strlen(ch) == 1)
1646 ch=strcat(buf,ch);
1647
1648
1649 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1650
1651 if(_syscmd(cmd,str,64) == RETURN_ERR)
1652 {
1653 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1654 return RETURN_ERR;
1655 }
1656
1657
1658 ch2=strchr(str,'\n');
1659 //replace \n with \0
1660 *ch2='\0';
1661 ch2=strchr(str,'=');
1662 if(ch2==NULL)
1663 {
1664 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1665 return RETURN_ERR;
1666 }
1667 else
1668 wifi_dbg_printf("%s",ch2+1);
1669
1670
1671 ch2++;
1672
1673
1674 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1675
1676 memset(buf,'\0',sizeof(buf));
1677 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1678 {
1679 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1680 return RETURN_ERR;
1681 }
1682 if (strstr(buf,"2.4") != NULL )
1683 strcpy(output_string,"2.4GHz");
1684 else if(strstr(buf,"5.") != NULL )
1685 strcpy(output_string,"5GHz");
1686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1687
1688 return RETURN_OK;
1689#endif
1690}
1691
1692//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1693//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.
1694INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1695{
developerb7593de2022-10-18 09:51:57 +08001696 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001697 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1698 if (NULL == output_string)
1699 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001700 band = wifi_index_to_band(radioIndex);
1701
1702 if (band == band_2_4)
1703 snprintf(output_string, 64, "2.4GHz");
1704 else if (band == band_5)
1705 snprintf(output_string, 64, "5GHz");
1706 else if (band == band_6)
1707 snprintf(output_string, 64, "6GHz");
1708
developer06a01d92022-09-07 16:32:39 +08001709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1710
1711 return RETURN_OK;
1712#if 0
1713 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1714 char buf[MAX_BUF_SIZE]={'\0'};
1715 char str[MAX_BUF_SIZE]={'\0'};
1716 char cmd[MAX_CMD_SIZE]={'\0'};
1717 char *ch=NULL;
1718 char *ch2=NULL;
1719 char ch1[5]="0";
1720
1721 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1722
1723 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1724 {
1725 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1726 return RETURN_ERR;
1727 }
1728
1729 ch=strchr(buf,'\n');
1730 *ch='\0';
1731 ch=strchr(buf,'=');
1732 if(ch==NULL)
1733 return RETURN_ERR;
1734 ch++;
1735
1736 if(strlen(ch)==1)
1737 {
1738 strcat(ch1,ch);
1739
1740 }
1741 else
1742 {
1743 strcpy(ch1,ch);
1744 }
1745
1746
1747
1748 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1749 if(_syscmd(cmd,str,64) == RETURN_ERR)
1750 {
1751 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1752 return RETURN_ERR;
1753 }
1754
1755
1756 ch2=strchr(str,'\n');
1757 //replace \n with \0
1758 *ch2='\0';
1759 ch2=strchr(str,'=');
1760 if(ch2==NULL)
1761 {
1762 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1763 return RETURN_ERR;
1764 }
1765 else
1766 wifi_dbg_printf("%s",ch2+1);
1767 ch2++;
1768
1769
1770 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1771 memset(buf,'\0',sizeof(buf));
1772 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1773 {
1774 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1775 return RETURN_ERR;
1776 }
1777
1778
1779 if(strstr(buf,"2.4")!=NULL)
1780 {
1781 strcpy(output_string,"2.4GHz");
1782 }
1783 if(strstr(buf,"5.")!=NULL)
1784 {
1785 strcpy(output_string,"5GHz");
1786 }
1787 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1788 return RETURN_OK;
1789#endif
1790}
1791
1792//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1793//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.
1794INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1795{
developer963da0c2022-09-13 15:58:27 +08001796 char cmd[128]={0};
1797 char buf[128]={0};
1798 char temp_output[128] = {0};
1799 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001800 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001801
1802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001803 if (NULL == output_string)
1804 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001805
1806 band = wifi_index_to_band(radioIndex);
1807 if (band == band_2_4) {
1808 strcat(temp_output, "b,g,");
1809 } else if (band == band_5) {
1810 strcat(temp_output, "a,");
1811 }
developer033b37b2022-10-18 11:27:46 +08001812 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001813 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001814 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 +08001815 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001816 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001817 strcat(temp_output, "n,");
1818 }
developer06a01d92022-09-07 16:32:39 +08001819
developer963da0c2022-09-13 15:58:27 +08001820 // vht capabilities
1821 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001822 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 +08001823 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001824 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001825 strcat(temp_output, "ac,");
1826 }
1827 }
1828
1829 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001830 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 +08001831 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001832 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001833 strcat(temp_output, "ax,");
1834 }
1835
developer7c4cd202023-03-01 10:56:29 +08001836 // eht capabilities
1837 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);
1838 _syscmd(cmd, buf, sizeof(buf));
1839 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1840 strcat(temp_output, "be,");
1841 }
1842
developer963da0c2022-09-13 15:58:27 +08001843 // Remove the last comma
1844 if (strlen(temp_output) != 0)
1845 temp_output[strlen(temp_output)-1] = '\0';
1846 strncpy(output_string, temp_output, strlen(temp_output));
1847 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001848 return RETURN_OK;
1849}
1850
1851//Get the radio operating mode, and pure mode flag. eg: "ac"
1852//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.
1853INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1854{
1855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1856 if (NULL == output_string)
1857 return RETURN_ERR;
1858
1859 if (radioIndex == 0) {
1860 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1861 *gOnly = FALSE;
1862 *nOnly = TRUE;
1863 *acOnly = FALSE;
1864 } else {
1865 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1866 *gOnly = FALSE;
1867 *nOnly = FALSE;
1868 *acOnly = FALSE;
1869 }
1870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1871
1872 return RETURN_OK;
1873#if 0
1874 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1875 char buf[64] = {0};
1876 char config_file[MAX_BUF_SIZE] = {0};
1877
1878 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1879 return RETURN_ERR;
1880
1881 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1882 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1883
1884 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1885 if (strlen(buf) == 0)
1886 {
1887 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1888 return RETURN_ERR;
1889 }
1890 if(strcmp(buf,"g")==0)
1891 {
1892 wifi_dbg_printf("\nG\n");
1893 *gOnly=TRUE;
1894 *nOnly=FALSE;
1895 *acOnly=FALSE;
1896 }
1897 else if(strcmp(buf,"n")==0)
1898 {
1899 wifi_dbg_printf("\nN\n");
1900 *gOnly=FALSE;
1901 *nOnly=TRUE;
1902 *acOnly=FALSE;
1903 }
1904 else if(strcmp(buf,"ac")==0)
1905 {
1906 wifi_dbg_printf("\nac\n");
1907 *gOnly=FALSE;
1908 *nOnly=FALSE;
1909 *acOnly=TRUE;
1910 }
1911 /* hostapd-5G.conf has "a" as hw_mode */
1912 else if(strcmp(buf,"a")==0)
1913 {
1914 wifi_dbg_printf("\na\n");
1915 *gOnly=FALSE;
1916 *nOnly=FALSE;
1917 *acOnly=FALSE;
1918 }
1919 else
1920 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1921
1922 //for a,n mode
1923 if(radioIndex == 1)
1924 {
1925 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1926 if(strcmp(buf,"1")==0)
1927 {
1928 strncpy(output_string, "n", 1);
1929 *nOnly=FALSE;
1930 }
1931 }
1932
1933 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1935 return RETURN_OK;
1936#endif
1937}
1938
developerdb744382022-09-13 15:34:54 +08001939INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1940{
1941 char cmd[128] = {0};
1942 char buf[64] = {0};
1943 char config_file[64] = {0};
1944 wifi_band band;
1945
1946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1947 if(NULL == output_string || NULL == pureMode)
1948 return RETURN_ERR;
1949
1950 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001951 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer7c4cd202023-03-01 10:56:29 +08001952 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 +08001953 _syscmd(cmd, buf, sizeof(buf));
1954
1955 band = wifi_index_to_band(radioIndex);
1956 // puremode is a bit map
1957 *pureMode = 0;
1958 if (band == band_2_4) {
1959 strcat(output_string, "b,g");
1960 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1961 if (strstr(buf, "n") != NULL) {
1962 strcat(output_string, ",n");
1963 *pureMode |= WIFI_MODE_N;
1964 }
1965 if (strstr(buf, "ax") != NULL) {
1966 strcat(output_string, ",ax");
1967 *pureMode |= WIFI_MODE_AX;
1968 }
developer7c4cd202023-03-01 10:56:29 +08001969 if (strstr(buf, "be") != NULL) {
1970 strcat(output_string, ",be");
1971 *pureMode |= WIFI_MODE_BE;
1972 }
developerdb744382022-09-13 15:34:54 +08001973 } else if (band == band_5) {
1974 strcat(output_string, "a");
1975 *pureMode |= WIFI_MODE_A;
1976 if (strstr(buf, "n") != NULL) {
1977 strcat(output_string, ",n");
1978 *pureMode |= WIFI_MODE_N;
1979 }
1980 if (strstr(buf, "ac") != NULL) {
1981 strcat(output_string, ",ac");
1982 *pureMode |= WIFI_MODE_AC;
1983 }
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 } else if (band == band_6) {
1993 if (strstr(buf, "ax") != NULL) {
1994 strcat(output_string, "ax");
1995 *pureMode |= WIFI_MODE_AX;
1996 }
developer7c4cd202023-03-01 10:56:29 +08001997 if (strstr(buf, "be") != NULL) {
1998 strcat(output_string, ",be");
1999 *pureMode |= WIFI_MODE_BE;
2000 }
developerdb744382022-09-13 15:34:54 +08002001 }
2002
2003 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2004 return RETURN_OK;
2005}
2006
2007// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08002008INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2009{
2010 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
2011 if (strcmp (channelMode,"11A") == 0)
2012 {
2013 writeBandWidth(radioIndex,"20MHz");
2014 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2015 printf("\nChannel Mode is 802.11a (5GHz)\n");
2016 }
2017 else if (strcmp (channelMode,"11NAHT20") == 0)
2018 {
2019 writeBandWidth(radioIndex,"20MHz");
2020 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2021 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2022 }
2023 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2024 {
2025 writeBandWidth(radioIndex,"40MHz");
2026 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2027 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2028 }
2029 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2030 {
2031 writeBandWidth(radioIndex,"40MHz");
2032 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2033 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2034 }
2035 else if (strcmp (channelMode,"11ACVHT20") == 0)
2036 {
2037 writeBandWidth(radioIndex,"20MHz");
2038 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2039 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2040 }
2041 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2042 {
2043 writeBandWidth(radioIndex,"40MHz");
2044 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2045 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2046 }
2047 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2048 {
2049 writeBandWidth(radioIndex,"40MHz");
2050 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2051 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2052 }
2053 else if (strcmp (channelMode,"11ACVHT80") == 0)
2054 {
2055 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2056 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2057 }
2058 else if (strcmp (channelMode,"11ACVHT160") == 0)
2059 {
2060 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2061 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2062 }
2063 else if (strcmp (channelMode,"11B") == 0)
2064 {
2065 writeBandWidth(radioIndex,"20MHz");
2066 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2067 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2068 }
2069 else if (strcmp (channelMode,"11G") == 0)
2070 {
2071 writeBandWidth(radioIndex,"20MHz");
2072 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2073 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2074 }
2075 else if (strcmp (channelMode,"11NGHT20") == 0)
2076 {
2077 writeBandWidth(radioIndex,"20MHz");
2078 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2079 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2080 }
2081 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2082 {
2083 writeBandWidth(radioIndex,"40MHz");
2084 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2085 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2086 }
2087 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2088 {
2089 writeBandWidth(radioIndex,"40MHz");
2090 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2091 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2092 }
2093 else
2094 {
2095 return RETURN_ERR;
2096 }
2097 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2098
2099 return RETURN_OK;
2100}
2101
developerdb744382022-09-13 15:34:54 +08002102// Set the radio operating mode, and pure mode flag.
2103INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2104{
developer7c4cd202023-03-01 10:56:29 +08002105 int num_hostapd_support_mode = 4; // n, ac, ax, be
developerdb744382022-09-13 15:34:54 +08002106 struct params list[num_hostapd_support_mode];
2107 char config_file[64] = {0};
2108 char bandwidth[16] = {0};
developer7c4cd202023-03-01 10:56:29 +08002109 char supported_mode[32] = {0};
developerdb744382022-09-13 15:34:54 +08002110 int mode_check_bit = 1 << 3; // n mode
developer7c4cd202023-03-01 10:56:29 +08002111 bool eht_support = FALSE;
developerdb744382022-09-13 15:34:54 +08002112
2113 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2114 // Set radio mode
2115 list[0].name = "ieee80211n";
2116 list[1].name = "ieee80211ac";
2117 list[2].name = "ieee80211ax";
developer7c4cd202023-03-01 10:56:29 +08002118 list[3].name = "ieee80211be";
developerdb744382022-09-13 15:34:54 +08002119 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2120
2121 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002122 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002123 list[0].value = "1";
2124 else
2125 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002126 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002127 list[1].value = "1";
2128 else
2129 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002130 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002131 list[2].value = "1";
2132 else
2133 list[2].value = "0";
developer7c4cd202023-03-01 10:56:29 +08002134 if (pureMode & WIFI_MODE_BE)
2135 list[3].value = "1";
2136 else
2137 list[3].value = "0";
2138
2139 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2140 if (strstr(supported_mode, "be") != NULL)
2141 eht_support = TRUE;
2142
2143 if (eht_support)
2144 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2145 else
2146 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode-1);
developerdb744382022-09-13 15:34:54 +08002147
2148 if (channelMode == NULL || strlen(channelMode) == 0)
2149 return RETURN_OK;
2150 // Set bandwidth
2151 if (strstr(channelMode, "40") != NULL)
2152 strcpy(bandwidth, "40MHz");
2153 else if (strstr(channelMode, "80") != NULL)
2154 strcpy(bandwidth, "80MHz");
2155 else if (strstr(channelMode, "160") != NULL)
2156 strcpy(bandwidth, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002157 else if (strstr(channelMode, "320") != NULL)
2158 strcpy(bandwidth, "320MHz");
developerdb744382022-09-13 15:34:54 +08002159 else // 11A, 11B, 11G....
2160 strcpy(bandwidth, "20MHz");
2161
2162 writeBandWidth(radioIndex, bandwidth);
2163 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2164
2165 wifi_reloadAp(radioIndex);
2166 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2167
2168 return RETURN_OK;
2169}
2170
developer1d12ebf2022-10-04 15:13:38 +08002171INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2172
2173 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002174 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002175 struct params params = {0};
2176 wifi_band band = band_invalid;
2177
2178 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2179
2180 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002181
2182 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002183 return RETURN_ERR;
2184 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2185 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002186 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2187 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002188
2189 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2190 params.name = "hw_mode";
2191 params.value = hw_mode;
2192 wifi_hostapdWrite(config_file, &params, 1);
2193 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2194
developeref938762022-10-19 17:21:01 +08002195 if (band == band_2_4) {
2196 if (strncmp(hw_mode, "b", 1) == 0) {
2197 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2198 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2199 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2200 snprintf(buf, sizeof(buf), "%s", "1,2");
2201 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2202 } else {
2203 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2204
2205 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2206 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2207 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2208 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2209 }
2210 }
2211
developer1d12ebf2022-10-04 15:13:38 +08002212 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2213 return RETURN_OK;
2214}
2215
developere8988ba2022-10-18 17:42:30 +08002216INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2217{
2218 char config_file[64] = {0};
2219 struct params params = {0};
2220 wifi_band band = band_invalid;
2221
2222 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2223
2224 band = wifi_index_to_band(radioIndex);
2225
2226 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2227 params.name = "noscan";
2228 params.value = noscan;
2229 wifi_hostapdWrite(config_file, &params, 1);
2230 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2231
2232 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2233 return RETURN_OK;
2234}
2235
developer06a01d92022-09-07 16:32:39 +08002236//Get the list of supported channel. eg: "1-11"
2237//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.
2238INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2239{
developer6318ed52022-09-13 15:17:58 +08002240 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002241 if (NULL == output_string)
2242 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002243 char cmd[256] = {0};
2244 char buf[128] = {0};
2245 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002246 int phyId = 0;
2247
developer6318ed52022-09-13 15:17:58 +08002248 // Parse possible channel number and separate them with commas.
2249 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002250 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002251 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002252 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002253 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 +08002254 else
developer033b37b2022-10-18 11:27:46 +08002255 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 +08002256
2257 _syscmd(cmd,buf,sizeof(buf));
2258 strncpy(output_string, buf, sizeof(buf));
2259
2260 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2261 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002262}
2263
2264//Get the list for used channel. eg: "1,6,9,11"
2265//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.
2266INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2267{
developerd946fd62022-12-08 18:03:28 +08002268 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002269 char cmd[128] = {0};
2270 char buf[128] = {0};
2271 char config_file[64] = {0};
2272 int channel = 0;
2273 int freq = 0;
2274 int bandwidth = 0;
2275 int center_freq = 0;
2276 int center_channel = 0;
2277 int channel_delta = 0;
2278 wifi_band band = band_invalid;
2279
2280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2281
developer06a01d92022-09-07 16:32:39 +08002282 if (NULL == output_string)
2283 return RETURN_ERR;
2284
developerac6f1142022-12-20 19:26:35 +08002285 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002286 return RETURN_ERR;
2287 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002288 _syscmd(cmd, buf, sizeof(buf));
2289 if (strlen(buf) == 0) {
2290 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2291 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002292 }
developerf5745ee2022-10-05 16:09:53 +08002293 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2294
2295 if (bandwidth == 20) {
2296 snprintf(output_string, 256, "%d", channel);
2297 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002298 }
developerf5745ee2022-10-05 16:09:53 +08002299
2300 center_channel = ieee80211_frequency_to_channel(center_freq);
2301
2302 band = wifi_index_to_band(radioIndex);
2303 if (band == band_2_4 && bandwidth == 40) {
2304 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2305 memset(buf, 0, sizeof(buf));
2306 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2307
developerf22724d2022-12-22 17:24:14 +08002308 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002309 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002310 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002311 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2312 } else {
2313 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2314 return RETURN_ERR;
2315 }
2316 } else if (band == band_5 || band == band_6){
2317 // 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 +08002318 // 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 +08002319 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002320 memset(output_string, 0, 256);
2321 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2322 // If i is not the last channel, we add a comma.
2323 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2324 strncat(output_string, buf, strlen(buf));
2325 }
developerf5745ee2022-10-05 16:09:53 +08002326 } else
2327 return RETURN_ERR;
2328
2329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002330 return RETURN_OK;
2331}
2332
2333//Get the running channel number
2334INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2335{
developer5b398df2022-11-17 20:39:48 +08002336 char channel_str[16] = {0};
2337 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002338
developer5b398df2022-11-17 20:39:48 +08002339 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002340 return RETURN_ERR;
2341
developer5b398df2022-11-17 20:39:48 +08002342 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2343 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002344
developer5b398df2022-11-17 20:39:48 +08002345 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002346
developer06a01d92022-09-07 16:32:39 +08002347 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002348}
2349
2350
2351INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2352{
2353 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002354 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002355
2356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2357 if (NULL == output_ulong)
2358 return RETURN_ERR;
2359
developer06a01d92022-09-07 16:32:39 +08002360 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002361 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2362 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002363 _syscmd(cmd,buf,sizeof(buf));
2364 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2365 if (*output_ulong == 0) {
2366 return RETURN_ERR;
2367 }
2368
2369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2370 return RETURN_OK;
2371}
2372
2373//Storing the previous channel value
2374INT wifi_storeprevchanval(INT radioIndex)
2375{
2376 char buf[256] = {0};
2377 char output[4]={'\0'};
2378 char config_file[MAX_BUF_SIZE] = {0};
2379 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2380 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2381 if(radioIndex == 0)
2382 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2383 else if(radioIndex == 1)
2384 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2385 system(buf);
2386 Radio_flag = FALSE;
2387 return RETURN_OK;
2388}
2389
2390//Set the running channel number
2391INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2392{
developer76989232022-10-04 14:13:19 +08002393 // We only write hostapd config here
2394 char str_channel[8]={0};
2395 char *list_channel;
2396 char config_file[128] = {0};
2397 char possible_channels[256] = {0};
2398 int max_radio_num = 0;
2399 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002400
developer76989232022-10-04 14:13:19 +08002401 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002402
developer76989232022-10-04 14:13:19 +08002403 // Check valid
2404 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002405
developer76989232022-10-04 14:13:19 +08002406 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2407 list_channel = strtok(possible_channels, ",");
2408 while(true)
developer06a01d92022-09-07 16:32:39 +08002409 {
developer76989232022-10-04 14:13:19 +08002410 if(list_channel == NULL) { // input not in the list
2411 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2412 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002413 }
developer76989232022-10-04 14:13:19 +08002414 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2415 break;
2416 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002417 }
2418
developer76989232022-10-04 14:13:19 +08002419 list.name = "channel";
2420 list.value = str_channel;
2421 wifi_getMaxRadioNumber(&max_radio_num);
2422 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002423 {
developer76989232022-10-04 14:13:19 +08002424 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2425 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002426 }
2427
developer76989232022-10-04 14:13:19 +08002428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002429 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002430}
developer06a01d92022-09-07 16:32:39 +08002431
2432INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2433{
developer7c4cd202023-03-01 10:56:29 +08002434 struct params list[3];
2435 char str_idx[16] = {0};
2436 char supported_mode[32] = {0};
2437 char config_file[64] = {0};
developer76989232022-10-04 14:13:19 +08002438 int max_num_radios = 0;
2439 wifi_band band = band_invalid;
developer7c4cd202023-03-01 10:56:29 +08002440 bool eht_support = FALSE;
developer76989232022-10-04 14:13:19 +08002441
2442 band = wifi_index_to_band(radioIndex);
2443 if (band == band_2_4)
2444 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002445
developer7c4cd202023-03-01 10:56:29 +08002446 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2447 if (strstr(supported_mode, "be") != NULL)
2448 eht_support = TRUE;
2449
developer30423732022-12-01 16:17:49 +08002450 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002451 list[0].name = "vht_oper_centr_freq_seg0_idx";
2452 list[0].value = str_idx;
2453 list[1].name = "he_oper_centr_freq_seg0_idx";
2454 list[1].value = str_idx;
developer7c4cd202023-03-01 10:56:29 +08002455 list[2].name = "eht_oper_centr_freq_seg0_idx";
2456 list[2].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002457
developer76989232022-10-04 14:13:19 +08002458 wifi_getMaxRadioNumber(&max_num_radios);
2459 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002460 {
developer76989232022-10-04 14:13:19 +08002461 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
developer7c4cd202023-03-01 10:56:29 +08002462 if (eht_support)
2463 wifi_hostapdWrite(config_file, list, 3);
developer76989232022-10-04 14:13:19 +08002464 else
2465 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002466 }
2467
2468 return RETURN_OK;
2469}
2470
2471//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2472//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2473INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2474{
2475 //Set to wifi config only. Wait for wifi reset to apply.
2476 char buf[256] = {0};
2477 char str_channel[256] = {0};
2478 int count = 0;
2479 ULONG Value = 0;
2480 FILE *fp = NULL;
2481 if(enable == TRUE)
2482 {
developer06a01d92022-09-07 16:32:39 +08002483 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002484 }
developer5884e982022-10-06 10:52:50 +08002485 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002486}
2487
developer0b246d12022-09-30 15:24:20 +08002488INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2489{
2490 if (output_bool == NULL)
2491 return RETURN_ERR;
2492
2493 *output_bool = TRUE;
2494
2495 return RETURN_OK;
2496}
2497
developer06a01d92022-09-07 16:32:39 +08002498INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2499{
2500 if (NULL == output_bool)
2501 return RETURN_ERR;
2502 *output_bool=FALSE;
2503 return RETURN_OK;
2504}
2505
2506INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2507{
2508 if (NULL == output_bool)
2509 return RETURN_ERR;
2510 *output_bool=FALSE;
2511 return RETURN_OK;
2512}
2513
2514INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2515{
2516 //Set to wifi config only. Wait for wifi reset to apply.
2517 return RETURN_OK;
2518}
2519
2520INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2521{
2522 return RETURN_OK;
2523}
2524
2525INT wifi_factoryResetAP(int apIndex)
2526{
developer838cca92022-10-03 13:19:57 +08002527 char ap_config_file[64] = {0};
2528 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002529 char buf[128] = {0};
developer89df4502023-02-16 20:45:02 +08002530 int max_radio_num = 0;
developer838cca92022-10-03 13:19:57 +08002531
developer06a01d92022-09-07 16:32:39 +08002532 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002533
2534 wifi_setApEnable(apIndex, FALSE);
2535 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2536 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002537 _syscmd(cmd, buf, sizeof(buf));
developer89df4502023-02-16 20:45:02 +08002538 wifi_getMaxRadioNumber(&max_radio_num);
2539 if (apIndex <= max_radio_num) // The ap is default radio interface, we should default up it.
2540 wifi_setApEnable(apIndex, TRUE);
developer838cca92022-10-03 13:19:57 +08002541
developer06a01d92022-09-07 16:32:39 +08002542 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002543
developer06a01d92022-09-07 16:32:39 +08002544 return RETURN_OK;
2545}
2546
2547//To set Band Steering AP group
2548//To-do
2549INT wifi_setBandSteeringApGroup(char *ApGroup)
2550{
2551 return RETURN_OK;
2552}
2553
developer1e5aa162022-09-13 16:06:24 +08002554INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2555{
2556 char config_file[128] = {'\0'};
2557 char buf[128] = {'\0'};
2558
2559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2560 if (dtimInterval == NULL)
2561 return RETURN_ERR;
2562
2563 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2564 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2565
2566 if (strlen(buf) == 0) {
2567 *dtimInterval = 2;
2568 } else {
2569 *dtimInterval = strtoul(buf, NULL, 10);
2570 }
2571
2572 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2573 return RETURN_OK;
2574}
2575
developer06a01d92022-09-07 16:32:39 +08002576INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2577{
developer5f222492022-09-13 15:21:52 +08002578 struct params params={0};
2579 char config_file[MAX_BUF_SIZE] = {'\0'};
2580 char buf[MAX_BUF_SIZE] = {'\0'};
2581
2582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2583 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002584 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002585 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002586 }
2587
2588 params.name = "dtim_period";
2589 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2590 params.value = buf;
2591
2592 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2593 wifi_hostapdWrite(config_file, &params, 1);
2594 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2595
2596 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2597 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002598}
2599
2600//Check if the driver support the Dfs
2601INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2602{
developer78a15382022-11-02 10:57:40 +08002603 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002604 if (NULL == output_bool)
2605 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002606 *output_bool=FALSE;
2607
2608 band = wifi_index_to_band(radioIndex);
2609 if (band == band_5)
2610 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002611 return RETURN_OK;
2612}
2613
2614//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.
2615//The value of this parameter is a comma seperated list of channel number
2616INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2617{
2618 if (NULL == output_pool)
2619 return RETURN_ERR;
2620 if (radioIndex==1)
2621 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2622 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2623
2624 return RETURN_OK;
2625}
2626
2627INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2628{
2629 //Set to wifi config. And apply instantly.
2630 return RETURN_OK;
2631}
2632
2633INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2634{
2635 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2636 return RETURN_ERR;
2637 *output_interval_seconds=1800;
2638 *output_dwell_milliseconds=40;
2639
2640 return RETURN_OK;
2641}
2642
2643INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2644{
2645 //Set to wifi config. And apply instantly.
2646 return RETURN_OK;
2647}
2648
developerbfc18512022-10-05 17:54:28 +08002649INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2650{
2651 if (output_bool == NULL)
2652 return RETURN_ERR;
2653 *output_bool = true;
2654 return RETURN_OK;
2655}
2656
2657INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2658{
2659 return RETURN_OK;
2660}
2661
developer06a01d92022-09-07 16:32:39 +08002662//Get the Dfs enable status
2663INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2664{
developer9964b5b2022-09-13 15:59:34 +08002665 char buf[16] = {0};
2666 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002667
2668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2669
developer30423732022-12-01 16:17:49 +08002670 if (output_bool == NULL)
2671 return RETURN_ERR;
2672
developer9964b5b2022-09-13 15:59:34 +08002673 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002674 f = fopen(DFS_ENABLE_FILE, "r");
2675 if (f != NULL) {
2676 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002677 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002678 *output_bool = FALSE;
2679 fclose(f);
2680 }
2681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002682 return RETURN_OK;
2683}
2684
2685//Set the Dfs enable status
2686INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2687{
developer9964b5b2022-09-13 15:59:34 +08002688 char config_file[128] = {0};
2689 FILE *f = NULL;
2690 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002691
2692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2693
developer9964b5b2022-09-13 15:59:34 +08002694 f = fopen(DFS_ENABLE_FILE, "w");
2695 if (f == NULL)
2696 return RETURN_ERR;
2697 fprintf(f, "%d", enable);
2698 fclose(f);
2699
2700 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002701 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002702 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2703 wifi_hostapdWrite(config_file, &params, 1);
2704 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2705
2706 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2707
developer9964b5b2022-09-13 15:59:34 +08002708 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002709 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002710}
2711
2712//Check if the driver support the AutoChannelRefreshPeriod
2713INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2714{
2715 if (NULL == output_bool)
2716 return RETURN_ERR;
2717 *output_bool=FALSE; //not support
2718
2719 return RETURN_OK;
2720}
2721
2722//Get the ACS refresh period in seconds
2723INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2724{
2725 if (NULL == output_ulong)
2726 return RETURN_ERR;
2727 *output_ulong=300;
2728
2729 return RETURN_OK;
2730}
2731
2732//Set the ACS refresh period in seconds
2733INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2734{
2735 return RETURN_ERR;
2736}
2737
developer7c4cd202023-03-01 10:56:29 +08002738INT getEHT320ChannelBandwidthSet(int radioIndex, int *BandwidthSet)
2739{
2740 int center_channel = 0;
2741 char config_file[32] = {0};
2742 char buf[32] = {0};
2743
2744 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2745 wifi_hostapdRead(config_file, "eht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2746
2747 center_channel = strtoul(buf, NULL, 10);
2748 center_channel += 1; // Add 1 to become muiltiple of 16
2749 if (center_channel % 64 == 32)
2750 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_1MHZ;
2751 else if (center_channel % 64 == 0)
2752 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_2MHZ;
2753 else
2754 return RETURN_ERR;
2755 return RETURN_OK;
2756}
2757
developer06a01d92022-09-07 16:32:39 +08002758//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2759//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.
2760INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2761{
developer72ec5572023-01-05 16:27:13 +08002762 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002763 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002764 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002765 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002766 wifi_band band;
developer70490032022-09-13 15:45:20 +08002767
2768 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2769
developer06a01d92022-09-07 16:32:39 +08002770 if (NULL == output_string)
2771 return RETURN_ERR;
2772
developer70490032022-09-13 15:45:20 +08002773 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2774 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002775
developer70490032022-09-13 15:45:20 +08002776 if (radio_enable != TRUE)
2777 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002778
developerfa41b1f2023-01-06 10:25:51 +08002779 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002780 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002781 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002782 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2783 snprintf(output_string, 64, "20MHz");
2784 else
2785 snprintf(output_string, 64, "40MHz");
2786
2787 } else {
2788 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2789 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2790 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2791 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2792 if (strncmp(buf, "0", 1) == 0)
2793 snprintf(output_string, 64, "20MHz");
2794 else
2795 snprintf(output_string, 64, "40MHz");
2796
2797 } else if (strncmp(buf, "1", 1) == 0)
2798 snprintf(output_string, 64, "80MHz");
developer7c4cd202023-03-01 10:56:29 +08002799 else if (strncmp(buf, "2", 1) == 0) {
developer72ec5572023-01-05 16:27:13 +08002800 snprintf(output_string, 64, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002801 wifi_hostapdRead(config_file, "eht_oper_chwidth", buf, sizeof(buf));
2802 if (strncmp(buf, "9", 1) == 0) {
2803 int BandwidthSet = 0;
2804 if (getEHT320ChannelBandwidthSet(radioIndex, &BandwidthSet) != RETURN_OK)
2805 return RETURN_ERR;
2806 if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_1MHZ)
2807 snprintf(output_string, 64, "320-1MHz");
2808 else if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_2MHZ)
2809 snprintf(output_string, 64, "320-2MHz");
2810 }
2811 }
developer06a01d92022-09-07 16:32:39 +08002812 }
developer72ec5572023-01-05 16:27:13 +08002813
developer06a01d92022-09-07 16:32:39 +08002814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002815
2816 return RETURN_OK;
2817}
2818
2819//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002820INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002821{
developerf7a466e2022-09-29 11:55:56 +08002822 char config_file[128];
2823 char set_value[16];
developer7c4cd202023-03-01 10:56:29 +08002824 char supported_mode[32] = {0};
2825 struct params params[3];
developerf7a466e2022-09-29 11:55:56 +08002826 int max_radio_num = 0;
developer7c4cd202023-03-01 10:56:29 +08002827 bool eht_support = FALSE;
developerf7a466e2022-09-29 11:55:56 +08002828
developer06a01d92022-09-07 16:32:39 +08002829 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002830
developerf7a466e2022-09-29 11:55:56 +08002831 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002832 return RETURN_ERR;
2833
developer7c4cd202023-03-01 10:56:29 +08002834 if(strstr(bandwidth,"160") != NULL || strstr(bandwidth,"320") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002835 strcpy(set_value, "2");
2836 else if(strstr(bandwidth,"80") != NULL)
2837 strcpy(set_value, "1");
2838 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2839 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002840 else if (strstr(bandwidth, "Auto") != NULL)
2841 return RETURN_OK;
2842 else {
developerf7a466e2022-09-29 11:55:56 +08002843 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002844 return RETURN_ERR;
2845 }
2846
developer7c4cd202023-03-01 10:56:29 +08002847 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2848 if (strstr(supported_mode, "be") != NULL)
2849 eht_support = TRUE;
2850
developerf7a466e2022-09-29 11:55:56 +08002851 params[0].name = "vht_oper_chwidth";
2852 params[0].value = set_value;
2853 params[1].name = "he_oper_chwidth";
2854 params[1].value = set_value;
developer7c4cd202023-03-01 10:56:29 +08002855 params[2].name = "eht_oper_chwidth";
2856 if (strstr(bandwidth,"320") != NULL) // We set oper_chwidth to 9 for EHT320
2857 params[2].value = "9";
2858 else
2859 params[2].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002860
developerf7a466e2022-09-29 11:55:56 +08002861 wifi_getMaxRadioNumber(&max_radio_num);
2862 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002863 {
developer7c4cd202023-03-01 10:56:29 +08002864 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2865 if (eht_support == TRUE)
2866 wifi_hostapdWrite(config_file, params, 3);
2867 else
2868 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002869 }
2870
2871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2872 return RETURN_OK;
2873}
2874
2875//Getting current radio extension channel
2876INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2877{
2878 CHAR buf[150] = {0};
2879 CHAR cmd[150] = {0};
2880 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2881 _syscmd(cmd, buf, sizeof(buf));
2882 if(NULL != strstr(buf,"HT40+"))
2883 strcpy(Value,"AboveControlChannel");
2884 else if(NULL != strstr(buf,"HT40-"))
2885 strcpy(Value,"BelowControlChannel");
2886 return RETURN_OK;
2887}
2888
2889//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2890//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.
2891INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2892{
developerfa41b1f2023-01-06 10:25:51 +08002893 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002894 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002895
2896 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002897 return RETURN_ERR;
2898
developerfa41b1f2023-01-06 10:25:51 +08002899 band = wifi_index_to_band(radioIndex);
2900 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002901 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002902
2903 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2904
2905 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002906 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002907
2908 return RETURN_OK;
2909}
2910
developer57fa24a2023-03-15 17:25:07 +08002911// This function handle 20MHz to remove HT40+/- in hostapd config, other bandwidths are handled in wifi_setRadioExtChannel.
2912INT wifi_RemoveRadioExtChannel(INT radioIndex, CHAR *ext_str)
2913{
2914 struct params params={0};
2915 char config_file[64] = {0};
2916 char ht_capab[128]={0};
2917 char buf[128] = {0};
2918 char cmd[128] = {0};
2919 int max_radio_num =0;
2920 bool stbcEnable = FALSE;
2921
2922 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2923 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2924 _syscmd(cmd, buf, sizeof(buf));
2925 if (strlen(buf) != 0)
2926 stbcEnable = TRUE;
2927
2928 strcpy(ht_capab, HOSTAPD_HT_CAPAB);
2929 params.value = ht_capab;
2930 params.name = "ht_capab";
2931
2932 wifi_getMaxRadioNumber(&max_radio_num);
2933 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2934 {
2935 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2936 wifi_hostapdWrite(config_file, &params, 1);
developer57fa24a2023-03-15 17:25:07 +08002937 }
developer8d7d0862023-05-18 16:50:23 +08002938 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer57fa24a2023-03-15 17:25:07 +08002939 return RETURN_OK;
2940}
2941
developer06a01d92022-09-07 16:32:39 +08002942//Set the extension channel.
2943INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer72ec5572023-01-05 16:27:13 +08002944{
developer06a01d92022-09-07 16:32:39 +08002945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002946 struct params params={0};
2947 char config_file[64] = {0};
2948 char ext_channel[128]={0};
2949 char buf[128] = {0};
2950 char cmd[128] = {0};
2951 int max_radio_num =0, ret = 0, bandwidth = 0;
developer72ec5572023-01-05 16:27:13 +08002952 unsigned long channel = 0;
developerfa41b1f2023-01-06 10:25:51 +08002953 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002954 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002955 wifi_band band;
2956
2957 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2958 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2959 _syscmd(cmd, buf, sizeof(buf));
2960 if (strlen(buf) != 0)
2961 stbcEnable = TRUE;
developer57fa24a2023-03-15 17:25:07 +08002962
2963 // readBandWidth get empty file will return error, that means we don't set new bandwidth
2964 if (readBandWidth(radioIndex, buf) != RETURN_OK) {
2965 // Get current bandwidth
2966 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2967 return RETURN_ERR;
2968 }
developerfa41b1f2023-01-06 10:25:51 +08002969 bandwidth = strtol(buf, NULL, 10);
2970 // TDK expected to get error with 20MHz
developer57fa24a2023-03-15 17:25:07 +08002971 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developerfa41b1f2023-01-06 10:25:51 +08002972 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2973 return RETURN_ERR;
2974
2975 band = wifi_index_to_band(radioIndex);
2976 if (band == band_invalid)
2977 return RETURN_ERR;
2978
2979 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2980 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002981
developer72ec5572023-01-05 16:27:13 +08002982 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2983 ret = util_get_sec_chan_offset(channel, buf);
2984 if (ret == -EINVAL)
2985 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002986
2987 if(NULL!= strstr(string,"Above")) {
developer72ec5572023-01-05 16:27:13 +08002988 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
2989 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002990 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08002991 } else if(NULL!= strstr(string,"Below")) {
developer72ec5572023-01-05 16:27:13 +08002992 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == 1))
2993 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002994 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08002995 } else {
developer57fa24a2023-03-15 17:25:07 +08002996 fprintf(stderr, "%s: unknow extchannel %s\n", __func__, string);
2997 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002998 }
developer06a01d92022-09-07 16:32:39 +08002999
3000 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08003001
3002 wifi_getMaxRadioNumber(&max_radio_num);
3003 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08003004 {
developer033b37b2022-10-18 11:27:46 +08003005 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08003006 wifi_hostapdWrite(config_file, &params, 1);
3007 }
developer8d7d0862023-05-18 16:50:23 +08003008 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer06a01d92022-09-07 16:32:39 +08003009
3010 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3011 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3012 return RETURN_OK;
3013}
3014
3015//Get the guard interval value. eg "400nsec" or "800nsec"
3016//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.
3017INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3018{
developer454b9462022-09-13 15:29:16 +08003019 wifi_guard_interval_t GI;
3020
3021 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3022
3023 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08003024 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08003025
3026 if (GI == wifi_guard_interval_400)
3027 strcpy(output_string, "400nsec");
3028 else if (GI == wifi_guard_interval_800)
3029 strcpy(output_string, "800nsec");
3030 else if (GI == wifi_guard_interval_1600)
3031 strcpy(output_string, "1600nsec");
3032 else if (GI == wifi_guard_interval_3200)
3033 strcpy(output_string, "3200nsec");
3034 else
developer78a15382022-11-02 10:57:40 +08003035 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08003036
developer454b9462022-09-13 15:29:16 +08003037 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003038 return RETURN_OK;
3039}
3040
3041//Set the guard interval value.
3042INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3043{
developer454b9462022-09-13 15:29:16 +08003044 wifi_guard_interval_t GI;
3045 int ret = 0;
3046
3047 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3048
3049 if (strcmp(string, "400nsec") == 0)
3050 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08003051 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08003052 GI = wifi_guard_interval_800;
3053 else if (strcmp(string , "1600nsec") == 0)
3054 GI = wifi_guard_interval_1600;
3055 else if (strcmp(string , "3200nsec") == 0)
3056 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08003057 else
3058 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08003059
3060 ret = wifi_setGuardInterval(radioIndex, GI);
3061
3062 if (ret == RETURN_ERR) {
3063 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3064 return RETURN_ERR;
3065 }
3066
3067 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3068 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003069}
3070
3071//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3072INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3073{
developerf49437e2022-09-29 19:58:21 +08003074 char buf[32]={0};
3075 char mcs_file[64] = {0};
3076 char cmd[64] = {0};
3077 int mode_bitmap = 0;
3078
3079 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3080 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08003081 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08003082 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3083
3084 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3085 _syscmd(cmd, buf, sizeof(buf));
3086 if (strlen(buf) > 0)
3087 *output_int = strtol(buf, NULL, 10);
3088 else {
3089 // output the max MCS for the current radio mode
3090 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3091 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3092 return RETURN_ERR;
3093 }
3094 if (mode_bitmap & WIFI_MODE_AX) {
3095 *output_int = 11;
3096 } else if (mode_bitmap & WIFI_MODE_AC) {
3097 *output_int = 9;
3098 } else if (mode_bitmap & WIFI_MODE_N) {
3099 *output_int = 7;
3100 }
3101 }
3102 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003103
3104 return RETURN_OK;
3105}
3106
3107//Set the Modulation Coding Scheme index
3108INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3109{
developerf49437e2022-09-29 19:58:21 +08003110 // 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).
3111 char config_file[64] = {0};
3112 char set_value[16] = {0};
3113 char mcs_file[32] = {0};
3114 wifi_band band = band_invalid;
3115 struct params set_config = {0};
3116 FILE *f = NULL;
3117
3118 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3119
3120 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3121
developer78a15382022-11-02 10:57:40 +08003122 // -1 means auto
3123 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08003124 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3125 return RETURN_ERR;
3126 }
3127
developer78a15382022-11-02 10:57:40 +08003128 if (MCS > 9 || MCS == -1)
3129 strcpy(set_value, "2");
3130 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08003131 strcpy(set_value, "1");
3132 else
developer78a15382022-11-02 10:57:40 +08003133 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08003134
3135 set_config.name = "he_basic_mcs_nss_set";
3136 set_config.value = set_value;
3137
3138 wifi_hostapdWrite(config_file, &set_config, 1);
3139 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3140
3141 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3142 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3143 f = fopen(mcs_file, "w");
3144 if (f == NULL) {
3145 fprintf(stderr, "%s: fopen failed\n", __func__);
3146 return RETURN_ERR;
3147 }
3148 fprintf(f, "%d", MCS);
3149 fclose(f);
3150
3151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3152 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003153}
3154
3155//Get supported Transmit Power list, eg : "0,25,50,75,100"
3156//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.
3157INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3158{
3159 if (NULL == output_list)
3160 return RETURN_ERR;
developer5c97d532023-09-28 11:19:30 +08003161 snprintf(output_list, 64,"0,12,25,50,75,100");
developer06a01d92022-09-07 16:32:39 +08003162 return RETURN_OK;
3163}
3164
developer5c97d532023-09-28 11:19:30 +08003165// Get current Transmit Power in percent
developer06a01d92022-09-07 16:32:39 +08003166INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3167{
developer5c97d532023-09-28 11:19:30 +08003168 char cmd[128]={'\0'};
3169 char buf[128]={'\0'};
3170 int phyIndex = -1;
3171 bool enabled = false;
3172 int cur_tx_dbm = 0;
3173
developera5005b62022-09-13 15:43:35 +08003174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003175
developera5005b62022-09-13 15:43:35 +08003176 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003177 return RETURN_ERR;
3178
developer5c97d532023-09-28 11:19:30 +08003179 phyIndex = radio_index_to_phy(radioIndex);
3180
3181 // Get the maximum tx power of the device
3182 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
3183 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developer06a01d92022-09-07 16:32:39 +08003184 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003185 if (strcmp(buf, "enable") == 0)
3186 enabled = true;
developer06a01d92022-09-07 16:32:39 +08003187
developer5c97d532023-09-28 11:19:30 +08003188 if (!enabled) {
3189 *output_ulong = 100;
3190 return RETURN_OK;
3191 }
developera5005b62022-09-13 15:43:35 +08003192
developer5c97d532023-09-28 11:19:30 +08003193 memset(cmd, 0, sizeof(cmd));
3194 memset(buf, 0, sizeof(buf));
3195 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
3196 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
3197 _syscmd(cmd, buf, sizeof(buf));
3198 cur_tx_dbm = strtol(buf, NULL, 10);
3199
3200 switch (cur_tx_dbm) {
3201 case 0:
3202 *output_ulong = 100; // range 91-100
3203 break;
3204 case 1:
3205 *output_ulong = 75; // range 61-90
3206 break;
3207 case 3:
3208 *output_ulong = 50; // range 31-60
3209 break;
3210 case 6:
3211 *output_ulong = 25; // range 16-30
3212 break;
3213 case 9:
3214 *output_ulong = 12; // range 10-15
3215 break;
3216 case 12:
3217 *output_ulong = 6; // range 1-9
3218 break;
3219 default:
3220 *output_ulong = 100; // 0
3221 }
3222
developer06a01d92022-09-07 16:32:39 +08003223 return RETURN_OK;
3224}
3225
developer5c97d532023-09-28 11:19:30 +08003226// TransmitPower: the the percentage relative to the maximum power,
3227// only support 0,12,25,50,75,100, But 0 means disable Power limit,
3228// so the power is 100%
developer06a01d92022-09-07 16:32:39 +08003229INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3230{
developerd946fd62022-12-08 18:03:28 +08003231 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003232 char *support;
developer06a01d92022-09-07 16:32:39 +08003233 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003234 char buf[128]={0};
3235 char txpower_str[64] = {0};
developer033b37b2022-10-18 11:27:46 +08003236 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003237
3238 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003239
developerac6f1142022-12-20 19:26:35 +08003240 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003241 return RETURN_ERR;
developera5005b62022-09-13 15:43:35 +08003242
3243 // Get the Tx power supported list and check that is the input in the list
3244 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3245 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3246 support = strtok(buf, ",");
3247 while(true)
3248 {
3249 if(support == NULL) { // input not in the list
3250 wifi_dbg_printf("Input value is invalid.\n");
3251 return RETURN_ERR;
3252 }
3253 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3254 break;
3255 }
3256 support = strtok(NULL, ",");
3257 }
developer5c97d532023-09-28 11:19:30 +08003258
developer033b37b2022-10-18 11:27:46 +08003259 phyId = radio_index_to_phy(radioIndex);
developer5c97d532023-09-28 11:19:30 +08003260 snprintf(cmd, sizeof(cmd), "echo %lu > /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_level",
3261 TransmitPower, phyId);
developera5005b62022-09-13 15:43:35 +08003262 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003263
developera5005b62022-09-13 15:43:35 +08003264 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003265
3266 return RETURN_OK;
3267}
3268
3269//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3270INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3271{
3272 if (NULL == Supported)
3273 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003274 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003275
3276 return RETURN_OK;
3277}
3278
3279//Get 80211h feature enable
3280INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3281{
developer3885fec2022-09-13 15:13:47 +08003282 char buf[64]={'\0'};
3283 char config_file[64] = {'\0'};
3284
3285 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3286 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003287 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003288
3289 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3290 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003291
developer3885fec2022-09-13 15:13:47 +08003292 if (strncmp(buf, "1", 1) == 0)
3293 *enable = TRUE;
3294 else
3295 *enable = FALSE;
3296
3297 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003298 return RETURN_OK;
3299}
3300
3301//Set 80211h feature enable
3302INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3303{
developer3885fec2022-09-13 15:13:47 +08003304 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3305 struct params params={'\0'};
3306 char config_file[MAX_BUF_SIZE] = {0};
3307
3308 params.name = "ieee80211h";
3309
3310 if (enable) {
3311 params.value = "1";
3312 } else {
3313 params.value = "0";
3314 }
3315
3316 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3317 wifi_hostapdWrite(config_file, &params, 1);
3318
3319 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3320 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3321 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003322}
3323
3324//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.
3325INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3326{
3327 if (NULL == output)
3328 return RETURN_ERR;
3329 *output=100;
3330
3331 return RETURN_OK;
3332}
3333
3334//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.
3335INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3336{
3337 if (NULL == output)
3338 return RETURN_ERR;
3339 *output = -99;
3340
3341 return RETURN_OK;
3342}
3343
3344INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3345{
3346 return RETURN_ERR;
3347}
3348
3349
3350//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3351INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3352{
developerd946fd62022-12-08 18:03:28 +08003353 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003354 char cmd[MAX_BUF_SIZE]={'\0'};
3355 char buf[MAX_CMD_SIZE]={'\0'};
3356
3357 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3358 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003359 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003360
developerac6f1142022-12-20 19:26:35 +08003361 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003362 return RETURN_ERR;
3363 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 +08003364 _syscmd(cmd, buf, sizeof(buf));
3365 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003366
developer5f222492022-09-13 15:21:52 +08003367 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003368 return RETURN_OK;
3369}
3370
3371INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3372{
developer5f222492022-09-13 15:21:52 +08003373 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3374 struct params params={'\0'};
3375 char buf[MAX_BUF_SIZE] = {'\0'};
3376 char config_file[MAX_BUF_SIZE] = {'\0'};
3377
developer5b398df2022-11-17 20:39:48 +08003378 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3379 return RETURN_ERR;
3380
developer5f222492022-09-13 15:21:52 +08003381 params.name = "beacon_int";
3382 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3383 params.value = buf;
3384
3385 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3386 wifi_hostapdWrite(config_file, &params, 1);
3387
3388 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3390 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003391}
3392
3393//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.
3394INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3395{
developer06a01d92022-09-07 16:32:39 +08003396 //TODO: need to revisit below implementation
3397 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003398 char temp_output[128] = {0};
3399 char temp_TransmitRates[64] = {0};
3400 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003401
3402 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3403 if (NULL == output)
3404 return RETURN_ERR;
3405 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003406 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3407
3408 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3409 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3410 } else {
3411 temp = strtok(temp_TransmitRates," ");
3412 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003413 {
developere9d0abd2022-09-13 15:40:57 +08003414 // Convert 100 kbps to Mbps
3415 temp[strlen(temp)-1]=0;
3416 if((temp[0]=='5') && (temp[1]=='\0'))
3417 {
3418 temp="5.5";
3419 }
3420 strcat(temp_output,temp);
3421 temp = strtok(NULL," ");
3422 if(temp!=NULL)
3423 {
3424 strcat(temp_output,",");
3425 }
developer06a01d92022-09-07 16:32:39 +08003426 }
developere9d0abd2022-09-13 15:40:57 +08003427 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003428 }
developer06a01d92022-09-07 16:32:39 +08003429 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003430 return RETURN_OK;
3431}
3432
3433INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3434{
3435 char *temp;
3436 char temp1[128];
3437 char temp_output[128];
3438 char temp_TransmitRates[128];
3439 char set[128];
3440 char sub_set[128];
3441 int set_count=0,subset_count=0;
3442 int set_index=0,subset_index=0;
3443 char *token;
3444 int flag=0, i=0;
3445 struct params params={'\0'};
3446 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003447 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003448
3449 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3450 if(NULL == TransmitRates)
3451 return RETURN_ERR;
3452 strcpy(sub_set,TransmitRates);
3453
3454 //Allow only supported Data transmit rate to be set
3455 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3456 token = strtok(sub_set,",");
3457 while( token != NULL ) /* split the basic rate to be set, by comma */
3458 {
3459 sub_set[subset_count]=atoi(token);
3460 subset_count++;
3461 token=strtok(NULL,",");
3462 }
3463 token=strtok(set,",");
3464 while(token!=NULL) /* split the supported rate by comma */
3465 {
3466 set[set_count]=atoi(token);
3467 set_count++;
3468 token=strtok(NULL,",");
3469 }
3470 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3471 {
3472 for(set_index=0;set_index < set_count;set_index++)
3473 {
3474 flag=0;
3475 if(sub_set[subset_index]==set[set_index])
3476 break;
3477 else
3478 flag=1; /* No match found */
3479 }
3480 if(flag==1)
3481 return RETURN_ERR; //If value not found return Error
3482 }
3483 strcpy(temp_TransmitRates,TransmitRates);
3484
3485 for(i=0;i<strlen(temp_TransmitRates);i++)
3486 {
3487 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003488 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003489 {
3490 continue;
3491 }
3492 else
3493 {
3494 return RETURN_ERR;
3495 }
3496 }
3497 strcpy(temp_output,"");
3498 temp = strtok(temp_TransmitRates,",");
3499 while(temp!=NULL)
3500 {
3501 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003502 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003503 {
developeref938762022-10-19 17:21:01 +08003504 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003505 {
3506 return RETURN_ERR;
3507 }
3508 }
3509
3510 if(strcmp(temp,"5.5")==0)
3511 {
3512 strcpy(temp1,"55");
3513 }
3514 else
3515 {
3516 strcat(temp1,"0");
3517 }
3518 strcat(temp_output,temp1);
3519 temp = strtok(NULL,",");
3520 if(temp!=NULL)
3521 {
3522 strcat(temp_output," ");
3523 }
3524 }
3525 strcpy(TransmitRates,temp_output);
3526
3527 params.name= "basic_rates";
3528 params.value =TransmitRates;
3529
3530 wifi_dbg_printf("\n%s:",__func__);
3531 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3532 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3533 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3534 wifi_hostapdWrite(config_file,&params,1);
3535 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3536 return RETURN_OK;
3537}
3538
3539//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003540INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003541{
3542 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3543 FILE *fp = NULL;
3544 char path[256] = {0}, output_string[256] = {0};
3545 int count = 0;
3546 char *interface = NULL;
3547
3548 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3549 if (fp == NULL)
3550 {
3551 printf("Failed to run command in Function %s\n", __FUNCTION__);
3552 return RETURN_ERR;
3553 }
3554 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3555 {
3556 interface = strchr(path, '=');
3557
3558 if (interface != NULL)
3559 {
3560 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003561 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003562 interface_name[count] = output_string[count];
3563
3564 interface_name[count] = '\0';
3565 }
3566 }
3567 pclose(fp);
3568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3569 return RETURN_OK;
3570}
3571
3572INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3573{
3574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3575 output_struct->radio_BytesSent = 0;
3576 output_struct->radio_BytesReceived = 0;
3577 output_struct->radio_PacketsSent = 0;
3578 output_struct->radio_PacketsReceived = 0;
3579 output_struct->radio_ErrorsSent = 0;
3580 output_struct->radio_ErrorsReceived = 0;
3581 output_struct->radio_DiscardPacketsSent = 0;
3582 output_struct->radio_DiscardPacketsReceived = 0;
3583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3584 return RETURN_OK;
3585}
3586
3587
3588INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3589{
3590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer214b0592023-10-31 10:59:05 +08003591 CHAR buf[MAX_CMD_SIZE] = {0};
3592 CHAR Value[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08003593 FILE *fp = NULL;
3594
3595 if (ifname == NULL || strlen(ifname) <= 1)
3596 return RETURN_OK;
3597
developer214b0592023-10-31 10:59:05 +08003598 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
developer06a01d92022-09-07 16:32:39 +08003599 system(buf);
3600
3601 fp = fopen("/tmp/Radio_Stats.txt", "r");
3602 if(fp == NULL)
3603 {
3604 printf("/tmp/Radio_Stats.txt not exists \n");
3605 return RETURN_ERR;
3606 }
3607 fclose(fp);
3608
developer214b0592023-10-31 10:59:05 +08003609 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3610 File_Reading(buf, Value);
3611 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003612
developer214b0592023-10-31 10:59:05 +08003613 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3614 File_Reading(buf, Value);
3615 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003616
developer214b0592023-10-31 10:59:05 +08003617 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3618 File_Reading(buf, Value);
3619 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003620
developer214b0592023-10-31 10:59:05 +08003621 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3622 File_Reading(buf, Value);
3623 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003624
developer214b0592023-10-31 10:59:05 +08003625 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3626 File_Reading(buf, Value);
3627 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003628
developer214b0592023-10-31 10:59:05 +08003629 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3630 File_Reading(buf, Value);
3631 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003632
developer214b0592023-10-31 10:59:05 +08003633 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3634 File_Reading(buf, Value);
3635 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003636
developer214b0592023-10-31 10:59:05 +08003637 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3638 File_Reading(buf, Value);
3639 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003640
3641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3642 return RETURN_OK;
3643}
3644
3645INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3646{
3647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3648 CHAR buf[MAX_CMD_SIZE] = {0};
3649 FILE *fp = NULL;
3650 INT count = 0;
3651
3652 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3653 {
3654 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3655 File_Reading(buf, status);
3656 }
3657 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3658 return RETURN_OK;
3659}
3660
3661//Get detail radio traffic static info
3662INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3663{
3664
3665#if 0
3666 //ifconfig radio_x
3667 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3668 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3669 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3670 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3671
3672 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3673 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3674 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.
3675 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.
3676
3677 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3678 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].
3679 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3680 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.
3681 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
3682 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
3683 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
3684 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
3685 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
3686
3687 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
3688 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
3689 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
3690 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.
3691
3692 return RETURN_OK;
3693#endif
3694
developera91d99f2022-09-29 15:59:10 +08003695 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003696 BOOL iface_status = FALSE;
3697 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer7c4c40e2023-10-25 10:17:04 +08003698 INT max_radio_num = 0, apIndex = 0;
developer06a01d92022-09-07 16:32:39 +08003699
3700 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3701 if (NULL == output_struct)
3702 return RETURN_ERR;
3703
developer7c4c40e2023-10-25 10:17:04 +08003704 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08003705
developer7c4c40e2023-10-25 10:17:04 +08003706 memset(output_struct, 0, sizeof(wifi_radioTrafficStats2_t));
developer06a01d92022-09-07 16:32:39 +08003707
developer7c4c40e2023-10-25 10:17:04 +08003708 for(apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
3709 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3710 continue;
3711 wifi_getApEnable(radioIndex, &iface_status);
3712
3713 if (iface_status == TRUE)
3714 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3715 else
3716 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003717
developer7c4c40e2023-10-25 10:17:04 +08003718 output_struct->radio_BytesSent += radioTrafficStats.radio_BytesSent;
3719 output_struct->radio_BytesReceived += radioTrafficStats.radio_BytesReceived;
3720 output_struct->radio_PacketsSent += radioTrafficStats.radio_PacketsSent;
3721 output_struct->radio_PacketsReceived += radioTrafficStats.radio_PacketsReceived;
3722 output_struct->radio_ErrorsSent += radioTrafficStats.radio_ErrorsSent;
3723 output_struct->radio_ErrorsReceived += radioTrafficStats.radio_ErrorsReceived;
3724 output_struct->radio_DiscardPacketsSent += radioTrafficStats.radio_DiscardPacketsSent;
3725 output_struct->radio_DiscardPacketsReceived += radioTrafficStats.radio_DiscardPacketsReceived;
3726 }
developer06a01d92022-09-07 16:32:39 +08003727
3728 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3729 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].
3730 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3731 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.
3732 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
3733 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
3734 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
3735 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
3736 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
3737
3738 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
3739 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
3740 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
3741 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.
3742
3743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3744
3745 return RETURN_OK;
3746}
3747
3748//Set radio traffic static Measureing rules
3749INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3750{
3751 //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
3752 // Else, save the MeasuringRate and MeasuringInterval for future usage
3753
3754 return RETURN_OK;
3755}
3756
3757//To start or stop RadioTrafficStats
3758INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3759{
3760 //zqiu: If the RadioTrafficStats process running
3761 // if(enable)
3762 // return RETURN_OK.
3763 // else
3764 // Stop RadioTrafficStats process
3765 // Else
3766 // if(enable)
3767 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3768 // else
3769 // return RETURN_OK.
3770
3771 return RETURN_OK;
3772}
3773
3774//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
3775INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3776{
3777 //zqiu: Please ignor signalIndex.
3778 if (NULL == SignalLevel)
3779 return RETURN_ERR;
3780 *SignalLevel=(radioIndex==0)?-19:-19;
3781
3782 return RETURN_OK;
3783}
3784
3785//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3786INT wifi_applyRadioSettings(INT radioIndex)
3787{
3788 return RETURN_OK;
3789}
3790
3791//Get the radio index assocated with this SSID entry
3792INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3793{
developer5b398df2022-11-17 20:39:48 +08003794 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003795 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003796 int max_radio_num = 0;
3797 wifi_getMaxRadioNumber(&max_radio_num);
3798 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003799 return RETURN_OK;
3800}
3801
3802//Device.WiFi.SSID.{i}.Enable
3803//Get SSID enable configuration parameters (not the SSID enable status)
3804INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3805{
3806 if (NULL == output_bool)
3807 return RETURN_ERR;
3808
developer06a01d92022-09-07 16:32:39 +08003809 return wifi_getApEnable(ssidIndex, output_bool);
3810}
3811
3812//Device.WiFi.SSID.{i}.Enable
3813//Set SSID enable configuration parameters
3814INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3815{
developer06a01d92022-09-07 16:32:39 +08003816 return wifi_setApEnable(ssidIndex, enable);
3817}
3818
3819//Device.WiFi.SSID.{i}.Status
3820//Get the SSID enable status
3821INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3822{
3823 char cmd[MAX_CMD_SIZE]={0};
3824 char buf[MAX_BUF_SIZE]={0};
3825 BOOL output_bool;
3826
3827 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3828 if (NULL == output_string)
3829 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003830
developer06a01d92022-09-07 16:32:39 +08003831 wifi_getApEnable(ssidIndex,&output_bool);
3832 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3833
3834 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3835 return RETURN_OK;
3836}
3837
3838// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3839INT wifi_getSSIDName(INT apIndex, CHAR *output)
3840{
3841 char config_file[MAX_BUF_SIZE] = {0};
3842
3843 if (NULL == output)
3844 return RETURN_ERR;
3845
developerefb790a2023-12-26 18:58:32 +08003846 if (!syn_flag) {
3847 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3848 wifi_hostapdRead(config_file,"ssid",output,32);
3849 } else
developer07ded1f2024-01-10 10:30:15 +08003850 snprintf(output, 32, "%s", vap_info[apIndex].ssid);
developer06a01d92022-09-07 16:32:39 +08003851
3852 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3853 return RETURN_OK;
3854}
3855
3856// Set a max 32 byte string and sets an internal variable to the SSID name
3857INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3858{
3859 char str[MAX_BUF_SIZE]={'\0'};
3860 char cmd[MAX_CMD_SIZE]={'\0'};
3861 struct params params;
3862 char config_file[MAX_BUF_SIZE] = {0};
3863
3864 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003865 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003866 return RETURN_ERR;
3867
3868 params.name = "ssid";
3869 params.value = ssid_string;
3870 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3871 wifi_hostapdWrite(config_file, &params, 1);
3872 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3874
3875 return RETURN_OK;
3876}
3877
3878//Get the BSSID
3879INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3880{
3881 char cmd[MAX_CMD_SIZE]="";
3882
3883 if (NULL == output_string)
3884 return RETURN_ERR;
3885
3886 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3887 {
developer1d57d002022-10-12 18:03:15 +08003888 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 +08003889 _syscmd(cmd, output_string, 64);
3890 return RETURN_OK;
3891 }
3892 strncpy(output_string, "\0", 1);
3893
3894 return RETURN_ERR;
3895}
3896
3897//Get the MAC address associated with this Wifi SSID
3898INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3899{
3900 wifi_getBaseBSSID(ssidIndex,output_string);
3901 return RETURN_OK;
3902}
3903
3904//Get the basic SSID traffic static info
3905//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3906//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3907INT wifi_applySSIDSettings(INT ssidIndex)
3908{
developerd946fd62022-12-08 18:03:28 +08003909 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003910 BOOL status = false;
3911 char cmd[MAX_CMD_SIZE] = {0};
3912 char buf[MAX_CMD_SIZE] = {0};
3913 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003914 int max_radio_num = 0;
3915 int radioIndex = 0;
3916
3917 wifi_getMaxRadioNumber(&max_radio_num);
3918
3919 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003920
3921 wifi_getApEnable(ssidIndex,&status);
3922 // Do not apply when ssid index is disabled
3923 if (status == false)
3924 return RETURN_OK;
3925
3926 /* Doing full remove and add for ssid Index
3927 * Not all hostapd options are supported with reload
3928 * for example macaddr_acl
3929 */
3930 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3931 return RETURN_ERR;
3932
3933 ret = wifi_setApEnable(ssidIndex,true);
3934
3935 /* Workaround for hostapd issue with multiple bss definitions
3936 * when first created interface will be removed
3937 * then all vaps other vaps on same phy are removed
3938 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003939 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003940 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003941 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003942 continue;
developer643b28f2023-04-04 10:26:01 +08003943 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003944 _syscmd(cmd, buf, sizeof(buf));
3945 if(*buf == '1')
3946 wifi_setApEnable(apIndex, true);
3947 }
3948
3949 return ret;
3950}
3951
developera3c68b92022-09-13 15:27:29 +08003952struct channels_noise {
3953 int channel;
3954 int noise;
3955};
3956
3957// Return noise array for each channel
3958int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3959{
developerd946fd62022-12-08 18:03:28 +08003960 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003961 FILE *f = NULL;
3962 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003963 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003964 size_t len = 0;
3965 ssize_t read = 0;
3966 int tmp = 0, arr_index = -1;
3967
developerac6f1142022-12-20 19:26:35 +08003968 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003969 return RETURN_ERR;
3970 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003971
3972 if ((f = popen(cmd, "r")) == NULL) {
3973 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3974 return RETURN_ERR;
3975 }
developer5550e242022-09-30 09:59:32 +08003976
3977 while(fgets(line, sizeof(line), f) != NULL) {
3978 if(arr_index < channels_num){
3979 sscanf(line, "%d", &tmp);
3980 if (tmp > 0) { // channel frequency, the first line must be frequency
3981 arr_index++;
3982 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3983 } else { // noise
3984 channels_noise_arr[arr_index].noise = tmp;
3985 }
3986 }else{
3987 break;
developera3c68b92022-09-13 15:27:29 +08003988 }
3989 }
developera3c68b92022-09-13 15:27:29 +08003990 pclose(f);
3991 return RETURN_OK;
3992}
3993
developer06a01d92022-09-07 16:32:39 +08003994//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3995//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3996INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3997{
developera3c68b92022-09-13 15:27:29 +08003998 int index = -1;
3999 wifi_neighbor_ap2_t *scan_array = NULL;
4000 char cmd[256]={0};
4001 char buf[128]={0};
4002 char file_name[32] = {0};
4003 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08004004 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004005 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08004006 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08004007 int freq=0;
4008 FILE *f = NULL;
4009 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08004010 int channels_num = 0;
4011 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08004012 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08004013 bool filter_enable = false;
4014 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08004015 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004016
developer615510b2022-09-27 10:14:35 +08004017 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004018
developerac6f1142022-12-20 19:26:35 +08004019 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004020 return RETURN_ERR;
4021
developera3c68b92022-09-13 15:27:29 +08004022 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4023 f = fopen(file_name, "r");
4024 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08004025 fgets(buf, sizeof(file_name), f);
4026 if ((strncmp(buf, "0", 1)) != 0) {
4027 fgets(filter_SSID, sizeof(file_name), f);
4028 if (strlen(filter_SSID) != 0)
4029 filter_enable = true;
4030 }
developera3c68b92022-09-13 15:27:29 +08004031 fclose(f);
4032 }
4033
developer033b37b2022-10-18 11:27:46 +08004034 phyId = radio_index_to_phy(radioIndex);
4035 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08004036 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08004037 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004038
developer5550e242022-09-30 09:59:32 +08004039
developer06a01d92022-09-07 16:32:39 +08004040
developerd946fd62022-12-08 18:03:28 +08004041 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4042 // 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 +08004043 fprintf(stderr, "cmd: %s\n", cmd);
4044 if ((f = popen(cmd, "r")) == NULL) {
4045 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4046 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004047 }
developer5550e242022-09-30 09:59:32 +08004048
4049 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4050 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
4051
developer615510b2022-09-27 10:14:35 +08004052 ret = fgets(line, sizeof(line), f);
4053 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08004054 if(strstr(line, "BSS") != NULL) { // new neighbor info
4055 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
4056 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4057 // 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 +08004058
developera3c68b92022-09-13 15:27:29 +08004059 if (!filter_BSS) {
4060 index++;
4061 wifi_neighbor_ap2_t *tmp;
4062 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4063 if (tmp == NULL) { // no more memory to use
4064 index--;
4065 wifi_dbg_printf("%s: realloc failed\n", __func__);
4066 break;
4067 }
4068 scan_array = tmp;
4069 }
4070 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4071
4072 filter_BSS = false;
4073 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4074 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4075 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4076 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4077 } else if (strstr(line, "freq") != NULL) {
4078 sscanf(line," freq: %d", &freq);
4079 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4080
4081 if (freq >= 2412 && freq <= 2484) {
4082 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4083 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4084 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4085 }
4086 else if (freq >= 5160 && freq <= 5805) {
4087 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4088 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4089 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4090 }
4091
4092 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08004093 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08004094 for (int i = 0; i < channels_num; i++) {
4095 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4096 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4097 break;
4098 }
4099 }
4100 }
4101 } else if (strstr(line, "beacon interval") != NULL) {
4102 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4103 } else if (strstr(line, "signal") != NULL) {
4104 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4105 } else if (strstr(line,"SSID") != NULL) {
4106 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4107 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4108 filter_BSS = true;
4109 }
4110 } else if (strstr(line, "Supported rates") != NULL) {
4111 char SRate[80] = {0}, *tmp = NULL;
4112 memset(buf, 0, sizeof(buf));
4113 strcpy(SRate, line);
4114 tmp = strtok(SRate, ":");
4115 tmp = strtok(NULL, ":");
4116 strcpy(buf, tmp);
4117 memset(SRate, 0, sizeof(SRate));
4118
4119 tmp = strtok(buf, " \n");
4120 while (tmp != NULL) {
4121 strcat(SRate, tmp);
4122 if (SRate[strlen(SRate) - 1] == '*') {
4123 SRate[strlen(SRate) - 1] = '\0';
4124 }
4125 strcat(SRate, ",");
4126
4127 tmp = strtok(NULL, " \n");
4128 }
4129 SRate[strlen(SRate) - 1] = '\0';
4130 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4131 } else if (strstr(line, "DTIM") != NULL) {
4132 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4133 } else if (strstr(line, "VHT capabilities") != NULL) {
4134 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4135 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4136 } else if (strstr(line, "HT capabilities") != NULL) {
4137 strcat(scan_array[index].ap_SupportedStandards, ",n");
4138 strcpy(scan_array[index].ap_OperatingStandards, "n");
4139 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004140 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004141 sscanf(line," * channel width: %d", &vht_channel_width);
4142 if(vht_channel_width == 1) {
4143 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4144 } else {
4145 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4146 }
4147 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4148 continue;
4149 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004150 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004151 sscanf(line," * secondary channel offset: %s", &buf);
4152 if (!strcmp(buf, "above")) {
4153 //40Mhz +
4154 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4155 }
4156 else if (!strcmp(buf, "below")) {
4157 //40Mhz -
4158 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4159 } else {
4160 //20Mhz
4161 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4162 }
4163 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4164 continue;
4165 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004166 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4167 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4168 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004169 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4170 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004171 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004172 else
developer615510b2022-09-27 10:14:35 +08004173 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004174 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004175 if (strstr(line, "HE80/5GHz") != NULL) {
4176 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4177 ret = fgets(line, sizeof(line), f);
4178 } else
4179 continue;
developera3c68b92022-09-13 15:27:29 +08004180 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004181 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004182 }
developer615510b2022-09-27 10:14:35 +08004183 continue;
developera3c68b92022-09-13 15:27:29 +08004184 } else if (strstr(line, "WPA") != NULL) {
4185 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4186 } else if (strstr(line, "RSN") != NULL) {
4187 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4188 } else if (strstr(line, "Group cipher") != NULL) {
4189 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4190 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4191 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4192 }
4193 }
developer615510b2022-09-27 10:14:35 +08004194 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004195 }
4196
4197 if (!filter_BSS) {
4198 *output_array_size = index + 1;
4199 } else {
4200 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4201 *output_array_size = index;
4202 }
4203 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004204 pclose(f);
developer5550e242022-09-30 09:59:32 +08004205 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004207 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004208}
4209
4210//>> Deprecated: used for old RDKB code.
4211INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4212{
4213 INT status = RETURN_ERR;
4214
4215 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4216 output_struct->wifi_PLCPErrorCount = 0;
4217 output_struct->wifi_FCSErrorCount = 0;
4218 output_struct->wifi_InvalidMACCount = 0;
4219 output_struct->wifi_PacketsOtherReceived = 0;
4220 output_struct->wifi_Noise = 0;
4221 status = RETURN_OK;
4222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4223 return status;
4224}
4225
4226INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4227{
developerd946fd62022-12-08 18:03:28 +08004228 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004229 char cmd[128] = {0};
4230 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004231 char *pos = NULL;
4232
4233 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4234 if (NULL == output_struct)
4235 return RETURN_ERR;
4236
developerac6f1142022-12-20 19:26:35 +08004237 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004238 return RETURN_ERR;
4239
developer06a01d92022-09-07 16:32:39 +08004240 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4241
developerd946fd62022-12-08 18:03:28 +08004242 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004243 _syscmd(cmd, buf, sizeof(buf));
4244
4245 pos = buf;
4246 if ((pos = strstr(pos, "RX packets:")) == NULL)
4247 return RETURN_ERR;
4248 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4249
4250 if ((pos = strstr(pos, "TX packets:")) == NULL)
4251 return RETURN_ERR;
4252 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4253
4254 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4255 return RETURN_ERR;
4256 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4257
4258 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4259 return RETURN_ERR;
4260 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4261
developerd946fd62022-12-08 18:03:28 +08004262 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004263 _syscmd(cmd, buf, sizeof(buf));
4264 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4265
4266#if 0
4267 //TODO: need to revisit below implementation
4268 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4269 char interface_name[MAX_BUF_SIZE] = {0};
4270 char interface_status[MAX_BUF_SIZE] = {0};
4271 char Value[MAX_BUF_SIZE] = {0};
4272 char buf[MAX_CMD_SIZE] = {0};
4273 char cmd[MAX_CMD_SIZE] = {0};
4274 FILE *fp = NULL;
4275
4276 if (NULL == output_struct) {
4277 return RETURN_ERR;
4278 }
4279
4280 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4281
4282 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4283 {
4284 if(apIndex == 0) //private_wifi for 2.4G
4285 {
developerac6f1142022-12-20 19:26:35 +08004286 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004287 }
4288 else if(apIndex == 1) //private_wifi for 5G
4289 {
developerac6f1142022-12-20 19:26:35 +08004290 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004291 }
4292 else if(apIndex == 4) //public_wifi for 2.4G
4293 {
4294 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4295 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4296 {
4297 return RETURN_ERR;
4298 }
4299 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004300 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004301 else//tenda
developerac6f1142022-12-20 19:26:35 +08004302 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004303 }
4304 else if(apIndex == 5) //public_wifi for 5G
4305 {
developerac6f1142022-12-20 19:26:35 +08004306 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004307 }
4308
4309 GetIfacestatus(interface_name, interface_status);
4310
4311 if(0 != strcmp(interface_status, "1"))
4312 return RETURN_ERR;
4313
4314 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4315 system(cmd);
4316
4317 fp = fopen("/tmp/SSID_Stats.txt", "r");
4318 if(fp == NULL)
4319 {
4320 printf("/tmp/SSID_Stats.txt not exists \n");
4321 return RETURN_ERR;
4322 }
4323 fclose(fp);
4324
4325 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4326 File_Reading(buf, Value);
4327 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4328
4329 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4330 File_Reading(buf, Value);
4331 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4332
4333 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4334 File_Reading(buf, Value);
4335 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4336
4337 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4338 File_Reading(buf, Value);
4339 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4340
4341 /* There is no specific parameter from caller to associate the value wifi_Associations */
4342 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4343 //_syscmd(cmd, buf, sizeof(buf));
4344 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4345 }
4346#endif
4347 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4348 return RETURN_OK;
4349}
4350
4351INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4352{
4353 char interface_name[MAX_BUF_SIZE] = {0};
4354 char interface_status[MAX_BUF_SIZE] = {0};
4355 char Value[MAX_BUF_SIZE] = {0};
4356 char buf[MAX_CMD_SIZE] = {0};
4357 char cmd[MAX_CMD_SIZE] = {0};
4358 FILE *fp = NULL;
4359
4360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4361 if (NULL == output_struct)
4362 return RETURN_ERR;
4363
4364 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4365
developerac6f1142022-12-20 19:26:35 +08004366 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004367 return RETURN_ERR;
4368 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004369
developerd946fd62022-12-08 18:03:28 +08004370 if(0 != strcmp(interface_status, "1"))
4371 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004372
developerd946fd62022-12-08 18:03:28 +08004373 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4374 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004375
developerd946fd62022-12-08 18:03:28 +08004376 fp = fopen("/tmp/SSID_Stats.txt", "r");
4377 if(fp == NULL)
4378 {
4379 printf("/tmp/SSID_Stats.txt not exists \n");
4380 return RETURN_ERR;
4381 }
4382 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004383
developerd946fd62022-12-08 18:03:28 +08004384 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4385 File_Reading(buf, Value);
4386 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004387
developerd946fd62022-12-08 18:03:28 +08004388 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4389 File_Reading(buf, Value);
4390 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004391
developerd946fd62022-12-08 18:03:28 +08004392 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4393 File_Reading(buf, Value);
4394 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004395
developerd946fd62022-12-08 18:03:28 +08004396 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4397 File_Reading(buf, Value);
4398 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004399
4400 output_struct->wifi_UnicastPacketsSent = 0;
4401 output_struct->wifi_UnicastPacketsReceived = 0;
4402 output_struct->wifi_MulticastPacketsSent = 0;
4403 output_struct->wifi_MulticastPacketsReceived = 0;
4404 output_struct->wifi_BroadcastPacketsSent = 0;
4405 output_struct->wifi_BroadcastPacketsRecevied = 0;
4406 output_struct->wifi_UnknownPacketsReceived = 0;
4407
4408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4409 return RETURN_OK;
4410}
4411
4412INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4413{
4414 INT status = RETURN_ERR;
4415
4416 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4417 //Below values should get updated from hal
4418 output_struct->wifi_RetransCount=0;
4419 output_struct->wifi_FailedRetransCount=0;
4420 output_struct->wifi_RetryCount=0;
4421 output_struct->wifi_MultipleRetryCount=0;
4422 output_struct->wifi_ACKFailureCount=0;
4423 output_struct->wifi_AggregatedPacketCount=0;
4424
4425 status = RETURN_OK;
4426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4427
4428 return status;
4429}
4430
4431INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4432{
4433 INT status = RETURN_ERR;
4434 UINT index;
4435 wifi_neighbor_ap_t *pt=NULL;
4436
4437 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4438 *output_array_size=2;
4439 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4440 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4441 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4442 strcpy(pt->ap_Radio,"");
4443 strcpy(pt->ap_SSID,"");
4444 strcpy(pt->ap_BSSID,"");
4445 strcpy(pt->ap_Mode,"");
4446 pt->ap_Channel=1;
4447 pt->ap_SignalStrength=0;
4448 strcpy(pt->ap_SecurityModeEnabled,"");
4449 strcpy(pt->ap_EncryptionMode,"");
4450 strcpy(pt->ap_OperatingFrequencyBand,"");
4451 strcpy(pt->ap_SupportedStandards,"");
4452 strcpy(pt->ap_OperatingStandards,"");
4453 strcpy(pt->ap_OperatingChannelBandwidth,"");
4454 pt->ap_BeaconPeriod=1;
4455 pt->ap_Noise=0;
4456 strcpy(pt->ap_BasicDataTransferRates,"");
4457 strcpy(pt->ap_SupportedDataTransferRates,"");
4458 pt->ap_DTIMPeriod=1;
4459 pt->ap_ChannelUtilization = 1;
4460 }
4461
4462 status = RETURN_OK;
4463 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4464
4465 return status;
4466}
4467
4468//----------------- AP HAL -------------------------------
4469
4470//>> Deprecated: used for old RDKB code.
4471INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4472{
4473 if (NULL == output_ulong || NULL == output_struct)
4474 return RETURN_ERR;
4475 *output_ulong = 0;
4476 *output_struct = NULL;
4477 return RETURN_OK;
4478}
4479
4480#ifdef HAL_NETLINK_IMPL
4481static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4482 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4483 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4484 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4485 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4486 char mac_addr[20];
4487 static int count=0;
4488 int rate=0;
4489
4490 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4491
4492 nla_parse(tb,
4493 NL80211_ATTR_MAX,
4494 genlmsg_attrdata(gnlh, 0),
4495 genlmsg_attrlen(gnlh, 0),
4496 NULL);
4497
4498 if(!tb[NL80211_ATTR_STA_INFO]) {
4499 fprintf(stderr, "sta stats missing!\n");
4500 return NL_SKIP;
4501 }
4502
4503
4504 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4505 fprintf(stderr, "failed to parse nested attributes!\n");
4506 return NL_SKIP;
4507 }
4508
4509 //devIndex starts from 1
4510 if( ++count == out->wifi_devIndex )
4511 {
4512 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4513 //Getting the mac addrress
4514 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4515
4516 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4517 fprintf(stderr, "failed to parse nested rate attributes!");
4518 return NL_SKIP;
4519 }
4520
4521 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4522 if(rinfo[NL80211_RATE_INFO_BITRATE])
4523 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4524 out->wifi_devTxRate = rate/10;
4525 }
4526
4527 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4528 fprintf(stderr, "failed to parse nested rate attributes!");
4529 return NL_SKIP;
4530 }
4531
4532 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4533 if(rinfo[NL80211_RATE_INFO_BITRATE])
4534 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4535 out->wifi_devRxRate = rate/10;
4536 }
4537 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4538 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4539
4540 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4541 count = 0; //starts the count for next cycle
4542 return NL_STOP;
4543 }
4544
4545 return NL_SKIP;
4546
4547}
4548#endif
4549
4550INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4551{
4552#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004553 Netlink nl = {0};
4554 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004555 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004556
developer30423732022-12-01 16:17:49 +08004557 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004558 info.wifi_devIndex = devIndex;
4559
developerac6f1142022-12-20 19:26:35 +08004560 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004561 return RETURN_ERR;
4562
4563 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004564
4565 nl.id = initSock80211(&nl);
4566
4567 if (nl.id < 0) {
4568 fprintf(stderr, "Error initializing netlink \n");
4569 return -1;
4570 }
4571
4572 struct nl_msg* msg = nlmsg_alloc();
4573
4574 if (!msg) {
4575 fprintf(stderr, "Failed to allocate netlink message.\n");
4576 nlfree(&nl);
4577 return -2;
4578 }
4579
4580 genlmsg_put(msg,
4581 NL_AUTO_PORT,
4582 NL_AUTO_SEQ,
4583 nl.id,
4584 0,
4585 NLM_F_DUMP,
4586 NL80211_CMD_GET_STATION,
4587 0);
4588
4589 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4590 nl_send_auto(nl.socket, msg);
4591 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4592 nl_recvmsgs(nl.socket, nl.cb);
4593 nlmsg_free(msg);
4594 nlfree(&nl);
4595
4596 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4597 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4598 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4599 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4600 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4601 return RETURN_OK;
4602#else
4603 //iw utility to retrieve station information
4604#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4605#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4606#define MACFILE "/tmp/wifi_AssoMac.txt"
4607#define TXRATEFILE "/tmp/wifi_txrate.txt"
4608#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4609 FILE *file = NULL;
4610 char if_name[10] = {'\0'};
4611 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004612 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004613 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004614 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004615
developerac6f1142022-12-20 19:26:35 +08004616 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004617 return RETURN_ERR;
4618
4619 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004620
4621 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4622 file = popen(pipeCmd, "r");
4623
4624 if(file == NULL)
4625 return RETURN_ERR; //popen failed
4626
4627 fgets(line, sizeof line, file);
4628 device = atoi(line);
4629 pclose(file);
4630
4631 if(device == 0)
4632 return RETURN_ERR; //No devices are connected
4633
4634 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4635 system(pipeCmd);
4636
4637 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4638
4639 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4640
4641 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4642
4643 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4644
4645 //devIndex starts from 1, ++count
4646 if((file = fopen(SIGNALFILE, "r")) != NULL )
4647 {
4648 for(count =0;fgets(line, sizeof line, file) != NULL;)
4649 {
4650 if (++count == devIndex)
4651 {
4652 output_struct->wifi_devSignalStrength = atoi(line);
4653 break;
4654 }
4655 }
4656 fclose(file);
4657 }
4658 else
4659 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4660
4661 if((file = fopen(MACFILE, "r")) != NULL )
4662 {
4663 for(count =0;fgets(line, sizeof line, file) != NULL;)
4664 {
4665 if (++count == devIndex)
4666 {
4667 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]);
4668 break;
4669 }
4670 }
4671 fclose(file);
4672 }
4673 else
4674 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4675
4676 if((file = fopen(TXRATEFILE, "r")) != NULL )
4677 {
4678 for(count =0;fgets(line, sizeof line, file) != NULL;)
4679 {
4680 if (++count == devIndex)
4681 {
4682 output_struct->wifi_devTxRate = atoi(line);
4683 break;
4684 }
4685 }
4686 fclose(file);
4687 }
4688 else
4689 fprintf(stderr,"fopen wifi_txrate.txt failed");
4690
4691 if((file = fopen(RXRATEFILE, "r")) != NULL)
4692 {
4693 for(count =0;fgets(line, sizeof line, file) != NULL;)
4694 {
4695 if (++count == devIndex)
4696 {
4697 output_struct->wifi_devRxRate = atoi(line);
4698 break;
4699 }
4700 }
4701 fclose(file);
4702 }
4703 else
4704 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4705
4706 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4707
4708 return RETURN_OK;
4709#endif
4710}
4711
4712INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4713{
4714 if (NULL == device)
4715 return RETURN_ERR;
4716 return RETURN_OK;
4717}
4718//<<
4719
4720
4721//--------------wifi_ap_hal-----------------------------
4722//enables CTS protection for the radio used by this AP
4723INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4724{
4725 //save config and Apply instantly
4726 return RETURN_ERR;
4727}
4728
4729// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4730INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4731{
developer463d39a2022-09-13 15:32:51 +08004732 char config_file[64] = {'\0'};
4733 char buf[64] = {'\0'};
4734 struct params list;
4735
4736 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4737 list.name = "ht_coex";
4738 snprintf(buf, sizeof(buf), "%d", enable);
4739 list.value = buf;
4740
4741 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4742 wifi_hostapdWrite(config_file, &list, 1);
4743 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4744
4745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4746
4747 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004748}
4749
4750//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4751INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4752{
developerea4bcce2022-09-13 15:26:13 +08004753 char config_file[MAX_BUF_SIZE] = {'\0'};
4754 char buf[MAX_BUF_SIZE] = {'\0'};
4755 struct params list;
4756
4757 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4758 if (threshold < 256 || threshold > 2346 )
4759 return RETURN_ERR;
4760 list.name = "fragm_threshold";
4761 snprintf(buf, sizeof(buf), "%d", threshold);
4762 list.value = buf;
4763
4764 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4765 wifi_hostapdWrite(config_file, &list, 1);
4766 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004767
developerea4bcce2022-09-13 15:26:13 +08004768 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004769
4770 return RETURN_OK;
4771}
4772
4773// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4774INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4775{
developer51a927d2022-09-13 15:42:22 +08004776 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004777 char cmd[512] = {'\0'};
4778 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004779 char stbc_config[16] = {'\0'};
4780 wifi_band band;
4781 int iterator = 0;
4782 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004783 int ant_count = 0;
4784 int ant_bitmap = 0;
4785 struct params list;
developer51a927d2022-09-13 15:42:22 +08004786
4787 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4788
4789 band = wifi_index_to_band(radioIndex);
4790 if (band == band_invalid)
4791 return RETURN_ERR;
4792
4793 if (band == band_2_4)
4794 iterator = 1;
4795 else if (band == band_5)
4796 iterator = 2;
4797 else
4798 return RETURN_OK;
4799
developer110b8a32022-12-26 15:56:44 +08004800 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4801 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4802 ant_count += ant_bitmap & 1;
4803
4804 if (ant_count == 1 && STBC_Enable == TRUE) {
4805 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4806 return RETURN_OK;
4807 }
4808
developer51a927d2022-09-13 15:42:22 +08004809 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4810
4811 // set ht and vht config
4812 for (int i = 0; i < iterator; i++) {
4813 memset(stbc_config, 0, sizeof(stbc_config));
4814 memset(cmd, 0, sizeof(cmd));
4815 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004816 list.name = (i == 0)?"ht_capab":"vht_capab";
4817 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004818 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4819 _syscmd(cmd, buf, sizeof(buf));
4820 if (strlen(buf) != 0)
4821 current_stbc = TRUE;
4822 if (current_stbc == STBC_Enable)
4823 continue;
4824
4825 if (STBC_Enable == TRUE) {
4826 // Append the STBC flags in capab config
4827 memset(cmd, 0, sizeof(cmd));
4828 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004829 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004830 else
developer6372c2b2022-10-27 17:39:51 +08004831 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 +08004832 _syscmd(cmd, buf, sizeof(buf));
4833 } else if (STBC_Enable == FALSE) {
4834 // Remove the STBC flags and remain other flags in capab
4835 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004836 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004837 _syscmd(cmd, buf, sizeof(buf));
4838 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004839 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004840 _syscmd(cmd, buf, sizeof(buf));
4841 }
developer110b8a32022-12-26 15:56:44 +08004842 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4843 list.value = buf;
4844 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004845 }
4846
4847 wifi_reloadAp(radioIndex);
4848
4849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4850 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004851}
4852
4853// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4854INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4855{
developerfe7aefc2022-12-23 17:13:37 +08004856 char cmd[128] = {0};
4857 char buf[128] = {0};
4858 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004859
4860 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4861
4862 if(output_bool == NULL)
4863 return RETURN_ERR;
4864
developerfe7aefc2022-12-23 17:13:37 +08004865 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4866 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004867
developerfe7aefc2022-12-23 17:13:37 +08004868 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4869 _syscmd(cmd, buf, sizeof(buf));
4870
4871 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004872 *output_bool = TRUE;
4873 else
4874 *output_bool = FALSE;
4875
4876 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4877 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004878}
4879
4880// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4881INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4882{
developerfe7aefc2022-12-23 17:13:37 +08004883 char config_file[128] = {0};
4884 struct params list = {0};
4885 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004886
4887 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4888
developerfe7aefc2022-12-23 17:13:37 +08004889 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004890 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004891
developerfe7aefc2022-12-23 17:13:37 +08004892 if (amsduEnable == enable)
4893 return RETURN_OK;
4894
4895 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4896 list.name = "amsdu";
4897 list.value = amsduEnable? "1":"0";
4898 wifi_hostapdWrite(config_file, &list, 1);
4899 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4900 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004901
4902 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4903 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004904}
4905
4906//P2 // outputs the number of Tx streams
4907INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4908{
developer2de97692022-09-26 14:00:03 +08004909 char buf[8] = {0};
4910 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004911 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004912
4913 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4914
developer033b37b2022-10-18 11:27:46 +08004915 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004916 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004917 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004918
developer110b8a32022-12-26 15:56:44 +08004919 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004920
4921 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4922
4923 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004924}
4925
developer110b8a32022-12-26 15:56:44 +08004926INT fitChainMask(INT radioIndex, int antcount)
4927{
4928 char buf[128] = {0};
4929 char cmd[128] = {0};
4930 char config_file[64] = {0};
4931 wifi_band band;
4932 struct params list[2] = {0};
4933
4934 band = wifi_index_to_band(radioIndex);
4935 if (band == band_invalid)
4936 return RETURN_ERR;
4937
4938 list[0].name = "he_mu_beamformer";
4939 list[1].name = "he_su_beamformer";
4940
4941 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4942 if (antcount == 1) {
4943 // remove config about multiple antennas
4944 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4945 _syscmd(cmd, buf, sizeof(buf));
4946
4947 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4948 _syscmd(cmd, buf, sizeof(buf));
4949
4950 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4951 _syscmd(cmd, buf, sizeof(buf));
4952
4953 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4954 _syscmd(cmd, buf, sizeof(buf));
4955
4956 list[0].value = "0";
4957 list[1].value = "0";
4958 } else {
4959 // 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.
4960 if (band == band_2_4 || band == band_5) {
4961 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4962 _syscmd(cmd, buf, sizeof(buf));
4963 if (strlen(buf) > 0) {
4964 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4965 _syscmd(cmd, buf, sizeof(buf));
4966 }
4967 }
4968 if (band == band_5) {
4969 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4970 _syscmd(cmd, buf, sizeof(buf));
4971 if (strlen(buf) > 0) {
4972 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4973 _syscmd(cmd, buf, sizeof(buf));
4974 }
4975 }
4976
4977 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4978 _syscmd(cmd, buf, sizeof(buf));
4979 if (strlen(buf) == 0) {
4980 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4981 _syscmd(cmd, buf, sizeof(buf));
4982 }
4983
4984 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4985 _syscmd(cmd, buf, sizeof(buf));
4986 if (strlen(buf) == 0) {
4987 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4988 _syscmd(cmd, buf, sizeof(buf));
4989 }
4990
4991 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4992 _syscmd(cmd, buf, sizeof(buf));
4993 if (strlen(buf) == 0) {
4994 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4995 } else {
4996 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4997 }
4998 _syscmd(cmd, buf, sizeof(buf));
4999
5000 list[0].value = "1";
5001 list[1].value = "1";
5002 }
5003 wifi_hostapdWrite(config_file, list, 2);
5004}
5005
developer06a01d92022-09-07 16:32:39 +08005006//P2 // sets the number of Tx streams to an enviornment variable
5007INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5008{
developer2de97692022-09-26 14:00:03 +08005009 char cmd[128] = {0};
5010 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08005011 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08005012 int cur_mask = 0;
5013 int antcount = 0;
5014 wifi_band band;
developer2de97692022-09-26 14:00:03 +08005015
5016 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5017
developer110b8a32022-12-26 15:56:44 +08005018 if (numStreams <= 0) {
5019 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08005020 return RETURN_ERR;
5021 }
developer110b8a32022-12-26 15:56:44 +08005022
5023 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
5024 if (cur_mask == numStreams)
5025 return RETURN_OK;
5026
developer2de97692022-09-26 14:00:03 +08005027 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08005028
5029 phyId = radio_index_to_phy(radioIndex);
5030 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08005031 _syscmd(cmd, buf, sizeof(buf));
5032
5033 if (strlen(buf) > 0) {
5034 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5035 return RETURN_ERR;
5036 }
developer2de97692022-09-26 14:00:03 +08005037
developer110b8a32022-12-26 15:56:44 +08005038 // if chain mask changed, we need to make the hostapd config valid.
5039 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5040 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08005041 }
developer110b8a32022-12-26 15:56:44 +08005042 fitChainMask(radioIndex, antcount);
5043
5044 wifi_setRadioEnable(radioIndex, TRUE);
5045
developer2de97692022-09-26 14:00:03 +08005046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5047 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005048}
5049
5050//P2 // outputs the number of Rx streams
5051INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5052{
developer110b8a32022-12-26 15:56:44 +08005053 char buf[8] = {0};
5054 char cmd[128] = {0};
5055 int phyId = 0;
5056
developer2de97692022-09-26 14:00:03 +08005057 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005058
5059 phyId = radio_index_to_phy(radioIndex);
5060 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5061 _syscmd(cmd, buf, sizeof(buf));
5062
5063 *output_int = (INT)strtol(buf, NULL, 16);
5064
developer2de97692022-09-26 14:00:03 +08005065 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005066
developer06a01d92022-09-07 16:32:39 +08005067 return RETURN_OK;
5068}
5069
5070//P2 // sets the number of Rx streams to an enviornment variable
5071INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5072{
developer2de97692022-09-26 14:00:03 +08005073 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5074 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5075 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5076 return RETURN_ERR;
5077 }
5078 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005079 return RETURN_ERR;
5080}
5081
5082//Get radio RDG enable setting
5083INT wifi_getRadioReverseDirectionGrantSupported(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//Get radio RDG enable setting
5092INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5093{
5094 if (NULL == output_bool)
5095 return RETURN_ERR;
5096 *output_bool = TRUE;
5097 return RETURN_OK;
5098}
5099
5100//Set radio RDG enable setting
5101INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5102{
5103 return RETURN_ERR;
5104}
5105
5106//Get radio ADDBA enable setting
5107INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5108{
5109 if (NULL == output_bool)
5110 return RETURN_ERR;
5111 *output_bool = TRUE;
5112 return RETURN_OK;
5113}
5114
5115//Set radio ADDBA enable setting
5116INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5117{
5118 return RETURN_ERR;
5119}
5120
5121//Get radio auto block ack enable setting
5122INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5123{
5124 if (NULL == output_bool)
5125 return RETURN_ERR;
5126 *output_bool = TRUE;
5127 return RETURN_OK;
5128}
5129
5130//Set radio auto block ack enable setting
5131INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5132{
5133 return RETURN_ERR;
5134}
5135
5136//Get radio 11n pure mode enable support
5137INT wifi_getRadio11nGreenfieldSupported(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//Get radio 11n pure mode enable setting
5146INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5147{
5148 if (NULL == output_bool)
5149 return RETURN_ERR;
5150 *output_bool = TRUE;
5151 return RETURN_OK;
5152}
5153
5154//Set radio 11n pure mode enable setting
5155INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5156{
5157 return RETURN_ERR;
5158}
5159
5160//Get radio IGMP snooping enable setting
5161INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5162{
developerd946fd62022-12-08 18:03:28 +08005163 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005164 char cmd[128]={0};
5165 char buf[4]={0};
5166 bool bridge = FALSE, mac80211 = FALSE;
5167 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5168
5169 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005170 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005171
5172 *output_bool = FALSE;
5173
5174 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5175 _syscmd(cmd, buf, sizeof(buf));
5176 if (strncmp(buf, "1", 1) == 0)
5177 bridge = TRUE;
5178
developerac6f1142022-12-20 19:26:35 +08005179 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005180 return RETURN_ERR;
5181 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 +08005182 _syscmd(cmd, buf, sizeof(buf));
5183 if (strncmp(buf, "1", 1) == 0)
5184 mac80211 = TRUE;
5185
5186 if (bridge && mac80211)
5187 *output_bool = TRUE;
5188
5189 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005190 return RETURN_OK;
5191}
5192
5193//Set radio IGMP snooping enable setting
5194INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5195{
developerd946fd62022-12-08 18:03:28 +08005196 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005197 char cmd[128]={0};
5198 char buf[4]={0};
developer894affa2023-05-10 18:13:19 +08005199 int max_num_radios = 0;
5200 int apIndex = 0;
developer81bf2ed2022-09-13 15:31:14 +08005201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5202
5203 // bridge
developerfb09ba62023-06-09 17:03:21 +08005204 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
developer81bf2ed2022-09-13 15:31:14 +08005205 _syscmd(cmd, buf, sizeof(buf));
5206
developer804c64f2022-10-19 13:54:40 +08005207 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005208 // mac80211
developer894affa2023-05-10 18:13:19 +08005209 for (int i = 0; i < MAX_NUM_VAP_PER_RADIO; i++) {
5210 apIndex = radioIndex + i*max_num_radios;
5211 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5212 continue;
developerfb09ba62023-06-09 17:03:21 +08005213 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 +08005214 _syscmd(cmd, buf, sizeof(buf));
5215 }
5216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5217 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005218}
5219
5220//Get the Reset count of radio
5221INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5222{
5223 if (NULL == output_int)
5224 return RETURN_ERR;
5225 *output_int = (radioIndex==0)? 1: 3;
5226
5227 return RETURN_OK;
5228}
5229
5230
5231//---------------------------------------------------------------------------------------------------
5232//
5233// Additional Wifi AP level APIs used for Access Point devices
5234//
5235//---------------------------------------------------------------------------------------------------
5236
5237// creates a new ap and pushes these parameters to the hardware
5238INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5239{
developer7930d352022-12-21 17:55:42 +08005240 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005241 return RETURN_OK;
5242}
5243
5244// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5245INT wifi_deleteAp(INT apIndex)
5246{
developerd946fd62022-12-08 18:03:28 +08005247 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005248 char buf[128] = {0};
5249 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005250
developerac6f1142022-12-20 19:26:35 +08005251 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005252 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005253
developer89df4502023-02-16 20:45:02 +08005254 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5255 return RETURN_ERR;
5256
developer7930d352022-12-21 17:55:42 +08005257 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005258 _syscmd(cmd, buf, sizeof(buf));
5259
5260 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005261 return RETURN_OK;
5262}
5263
5264// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5265INT wifi_getApName(INT apIndex, CHAR *output_string)
5266{
developerd946fd62022-12-08 18:03:28 +08005267 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005268 if(NULL == output_string)
5269 return RETURN_ERR;
5270
developerac6f1142022-12-20 19:26:35 +08005271 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005272 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005273 else
5274 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005275 return RETURN_OK;
5276}
5277
5278// Outputs the index number in that corresponds to the SSID string
5279INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5280{
developerd946fd62022-12-08 18:03:28 +08005281 char cmd [128] = {0};
5282 char buf[32] = {0};
5283 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005284 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005285
developerefb790a2023-12-26 18:58:32 +08005286#ifdef DYNAMIC_IF_NAME
developerd946fd62022-12-08 18:03:28 +08005287 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5288 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005289
developerac6f1142022-12-20 19:26:35 +08005290 if (strlen(buf) != 0) {
5291 apIndex_str = strtok(buf, "\n");
5292 *output_int = strtoul(apIndex_str, NULL, 10);
5293 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005294 }
developerefb790a2023-12-26 18:58:32 +08005295#endif
developer67b8ee92022-12-20 10:48:43 +08005296 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5297 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5298 if (apIndex_str) {
5299 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5300 return RETURN_OK;
5301 }
developerd946fd62022-12-08 18:03:28 +08005302 *output_int = -1;
5303 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005304}
5305
5306INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5307{
5308 return wifi_getIndexFromName(inputSsidString, output_int);
5309}
5310
5311// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5312INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5313{
5314 char buf[MAX_BUF_SIZE] = {0};
5315 char cmd[MAX_CMD_SIZE] = {0};
5316 char config_file[MAX_BUF_SIZE] = {0};
5317
5318 if(NULL == output_string)
5319 return RETURN_ERR;
5320
5321 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005322 if (!syn_flag)
5323 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5324 else
developer07ded1f2024-01-10 10:30:15 +08005325 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08005326 if((strcmp(buf,"3")==0))
5327 snprintf(output_string, 32, "WPAand11i");
5328 else if((strcmp(buf,"2")==0))
5329 snprintf(output_string, 32, "11i");
5330 else if((strcmp(buf,"1")==0))
5331 snprintf(output_string, 32, "WPA");
5332 else
5333 snprintf(output_string, 32, "None");
5334
5335 return RETURN_OK;
5336}
5337
5338// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5339INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5340{
5341 char config_file[MAX_BUF_SIZE] = {0};
5342 struct params list;
5343
5344 if (NULL == beaconTypeString)
5345 return RETURN_ERR;
5346 list.name = "wpa";
5347 list.value = "0";
5348
5349 if((strcmp(beaconTypeString,"WPAand11i")==0))
5350 list.value="3";
5351 else if((strcmp(beaconTypeString,"11i")==0))
5352 list.value="2";
5353 else if((strcmp(beaconTypeString,"WPA")==0))
5354 list.value="1";
5355
5356 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5357 wifi_hostapdWrite(config_file, &list, 1);
5358 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developerefb790a2023-12-26 18:58:32 +08005359 snprintf(vap_info[apIndex].wpa, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08005360 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5361 return RETURN_OK;
5362}
5363
5364// sets the beacon interval on the hardware for this AP
5365INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5366{
developer5f222492022-09-13 15:21:52 +08005367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5368 struct params params={'\0'};
5369 char buf[MAX_BUF_SIZE] = {'\0'};
5370 char config_file[MAX_BUF_SIZE] = {'\0'};
5371
5372 params.name = "beacon_int";
5373 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5374 params.value = buf;
5375
5376 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5377 wifi_hostapdWrite(config_file, &params, 1);
5378
5379 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5381 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005382}
5383
5384INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5385{
developer5b398df2022-11-17 20:39:48 +08005386 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5387 return RETURN_ERR;
5388 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005389}
5390
5391// Get the packet size threshold supported.
5392INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5393{
5394 //save config and apply instantly
5395 if (NULL == output_bool)
5396 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005397 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005398 return RETURN_OK;
5399}
5400
5401// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5402INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5403{
developer514406b2022-12-05 17:20:21 +08005404 char buf[16] = {0};
5405 char config_file[128] = {0};
5406 struct params param = {0};
5407
5408 if (threshold > 65535) {
5409 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5410 return RETURN_ERR;
5411 }
developer06a01d92022-09-07 16:32:39 +08005412
developer23e71282023-01-18 10:25:19 +08005413 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005414 snprintf(buf, sizeof(buf), "%u", threshold);
5415 param.name = "rts_threshold";
5416 param.value = buf;
5417 wifi_hostapdWrite(config_file, &param, 1);
5418 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5419 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005420
5421 return RETURN_OK;
5422}
5423
5424// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5425INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5426{
5427 if (NULL == output_string)
5428 return RETURN_ERR;
5429 snprintf(output_string, 32, "TKIPandAESEncryption");
5430 return RETURN_OK;
5431
5432}
5433
5434// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5435INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5436{
5437 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005438 char *param_name = NULL;
5439 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005440
5441 if(NULL == output_string)
5442 return RETURN_ERR;
5443
5444 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005445 if (!syn_flag)
5446 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5447 else
developer07ded1f2024-01-10 10:30:15 +08005448 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08005449
5450 if(strcmp(buf,"0")==0)
5451 {
5452 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5453 snprintf(output_string, 32, "None");
5454 return RETURN_OK;
5455 }
5456 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5457 param_name = "rsn_pairwise";
5458 else if((strcmp(buf,"1")==0))
5459 param_name = "wpa_pairwise";
5460 else
5461 return RETURN_ERR;
5462 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005463 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005464 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5465 param_name = "wpa_pairwise";
5466 memset(output_string, '\0', 32);
5467 wifi_hostapdRead(config_file, param_name, output_string, 32);
5468 }
developer06a01d92022-09-07 16:32:39 +08005469 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5470
developer72ec5572023-01-05 16:27:13 +08005471 if(strcmp(output_string,"TKIP CCMP") == 0)
5472 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5473 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005474 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5475 else if(strcmp(output_string,"CCMP") == 0)
5476 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005477
5478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5479 return RETURN_OK;
5480}
5481
5482// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5483INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5484{
5485 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5486 struct params params={'\0'};
5487 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005488 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005489
5490 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005491 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005492
5493 if(strcmp(encMode, "TKIPEncryption") == 0)
5494 params.value = "TKIP";
5495 else if(strcmp(encMode,"AESEncryption") == 0)
5496 params.value = "CCMP";
5497 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5498 params.value = "TKIP CCMP";
5499
5500 if((strcmp(output_string,"WPAand11i")==0))
5501 {
5502 params.name = "wpa_pairwise";
5503 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5504 wifi_hostapdWrite(config_file, &params, 1);
5505 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5506
developer30423732022-12-01 16:17:49 +08005507 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005508 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5509 wifi_hostapdWrite(config_file, &params, 1);
5510 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5511
5512 return RETURN_OK;
5513 }
5514 else if((strcmp(output_string,"11i")==0))
5515 {
5516 params.name = "rsn_pairwise";
5517 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5518 wifi_hostapdWrite(config_file, &params, 1);
5519 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5520 return RETURN_OK;
5521 }
5522 else if((strcmp(output_string,"WPA")==0))
5523 {
5524 params.name = "wpa_pairwise";
5525 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5526 wifi_hostapdWrite(config_file, &params, 1);
5527 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5528 return RETURN_OK;
5529 }
5530
5531 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5532 return RETURN_OK;
5533}
5534
5535// deletes internal security varable settings for this ap
5536INT wifi_removeApSecVaribles(INT apIndex)
5537{
5538 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005539 //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 +08005540 //_syscmd(cmd, buf, sizeof(buf));
5541
developerd946fd62022-12-08 18:03:28 +08005542 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005543 //_syscmd(cmd, buf, sizeof(buf));
5544 return RETURN_ERR;
5545}
5546
5547// changes the hardware settings to disable encryption on this ap
5548INT wifi_disableApEncryption(INT apIndex)
5549{
5550 //Apply instantly
5551 return RETURN_ERR;
5552}
5553
5554// set the authorization mode on this ap
5555// mode mapping as: 1: open, 2: shared, 4:auto
5556INT wifi_setApAuthMode(INT apIndex, INT mode)
5557{
developeraf95c502022-09-13 16:18:22 +08005558 struct params params={0};
5559 char config_file[64] = {0};
5560 int ret;
5561
5562 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5563
5564 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5565 params.name = "auth_algs";
5566
developer72ec5572023-01-05 16:27:13 +08005567 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005568 params.value = "3";
5569 else if (mode & 2)
5570 params.value = "2";
5571 else if (mode & 1)
5572 params.value = "1";
5573 else
5574 params.value = "0";
5575
5576 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5577 wifi_hostapdWrite(config_file, &params, 1);
5578 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005579 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5581
5582 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005583}
5584
5585// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5586INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5587{
5588 //save to wifi config, and wait for wifi restart to apply
5589 struct params params={'\0'};
5590 char config_file[MAX_BUF_SIZE] = {0};
5591 int ret;
5592
5593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5594 if(authMode == NULL)
5595 return RETURN_ERR;
5596
5597 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5598 params.name = "wpa_key_mgmt";
5599
5600 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5601 params.value = "WPA-PSK";
5602 else if(strcmp(authMode,"EAPAuthentication") == 0)
5603 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005604 else if (strcmp(authMode, "SAEAuthentication") == 0)
5605 params.value = "SAE";
5606 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5607 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005608 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5609 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005610 else if (strcmp(authMode, "Enhanced_Open") == 0)
5611 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005612 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5613 return RETURN_OK; //This is taken careof in beaconType
5614
5615 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5616 ret=wifi_hostapdWrite(config_file,&params,1);
5617 if(!ret)
5618 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
developerefb790a2023-12-26 18:58:32 +08005619 snprintf(vap_info[apIndex].wpa_key_mgmt, MAX_BUF_SIZE, "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08005620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5621
5622 return ret;
5623}
5624
5625// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5626INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5627{
5628 //save to wifi config, and wait for wifi restart to apply
5629 char BeaconType[50] = {0};
5630 char config_file[MAX_BUF_SIZE] = {0};
5631
5632 *authMode = 0;
5633 wifi_getApBeaconType(apIndex,BeaconType);
5634 printf("%s____%s \n",__FUNCTION__,BeaconType);
5635
5636 if(strcmp(BeaconType,"None") == 0)
5637 strcpy(authMode,"None");
5638 else
5639 {
5640 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005641 if (!syn_flag)
5642 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5643 else
developer07ded1f2024-01-10 10:30:15 +08005644 snprintf(authMode, 32, "%s", vap_info[apIndex].wpa_key_mgmt);
developer06a01d92022-09-07 16:32:39 +08005645 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5646 if(strcmp(authMode,"WPA-PSK") == 0)
5647 strcpy(authMode,"SharedAuthentication");
5648 else if(strcmp(authMode,"WPA-EAP") == 0)
5649 strcpy(authMode,"EAPAuthentication");
5650 }
5651
5652 return RETURN_OK;
5653}
5654
5655// Outputs the number of stations associated per AP
5656INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5657{
developerd946fd62022-12-08 18:03:28 +08005658 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005659 char cmd[128]={0};
5660 char buf[128]={0};
5661 BOOL status = false;
5662
5663 if(apIndex > MAX_APS)
5664 return RETURN_ERR;
5665
5666 wifi_getApEnable(apIndex,&status);
5667 if (!status)
5668 return RETURN_OK;
5669
developerd946fd62022-12-08 18:03:28 +08005670 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005671 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005672 return RETURN_ERR;
5673 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005674 _syscmd(cmd, buf, sizeof(buf));
5675 sscanf(buf,"%lu", output_ulong);
5676
5677 return RETURN_OK;
5678}
5679
5680// manually removes any active wi-fi association with the device specified on this ap
5681INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5682{
developerd946fd62022-12-08 18:03:28 +08005683 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005684 char buf[126]={'\0'};
5685
developerac6f1142022-12-20 19:26:35 +08005686 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005687 return RETURN_ERR;
5688 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005689 system(buf);
5690
5691 return RETURN_OK;
5692}
5693
5694// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5695INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5696{
5697 if(NULL == output_int)
5698 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005699 int max_radio_num = 0;
5700 wifi_getMaxRadioNumber(&max_radio_num);
5701 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005702 return RETURN_OK;
5703}
5704
5705// sets the radio index for the specific ap
5706INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5707{
5708 //set to config only and wait for wifi reset to apply settings
5709 return RETURN_ERR;
5710}
5711
5712// Get the ACL MAC list per AP
5713INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5714{
developerd946fd62022-12-08 18:03:28 +08005715 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005716 char cmd[MAX_CMD_SIZE]={'\0'};
5717 int ret = 0;
5718
developerac6f1142022-12-20 19:26:35 +08005719 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005720 return RETURN_ERR;
5721 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005722 ret = _syscmd(cmd,macArray,buf_size);
5723 if (ret != 0)
5724 return RETURN_ERR;
5725
5726 return RETURN_OK;
5727}
5728
developere6aafda2022-09-13 14:59:28 +08005729INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5730{
developerd946fd62022-12-08 18:03:28 +08005731 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005732 char cmd[MAX_CMD_SIZE]={'\0'};
5733 int ret = 0;
5734
developerac6f1142022-12-20 19:26:35 +08005735 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005736 return RETURN_ERR;
5737 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005738 ret = _syscmd(cmd,macArray,buf_size);
5739 if (ret != 0)
5740 return RETURN_ERR;
5741
5742 return RETURN_OK;
5743}
5744
developer06a01d92022-09-07 16:32:39 +08005745// Get the list of stations associated per AP
5746INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5747{
developerd946fd62022-12-08 18:03:28 +08005748 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005749 char cmd[128];
5750
5751 if(apIndex > 3) //Currently supporting apIndex upto 3
5752 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005753 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005754 return RETURN_ERR;
5755 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5756 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005757 _syscmd(cmd, macArray, buf_size);
5758
5759 return RETURN_OK;
5760}
5761
developer2f995fb2023-02-24 10:40:44 +08005762INT getAddressControlMode(INT apIndex, INT *mode)
5763{
5764 char buf [16] = {0};
5765 char config_file[64] = {0};
5766
5767 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08005768 if (!syn_flag)
5769 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5770 else
developer07ded1f2024-01-10 10:30:15 +08005771 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer2f995fb2023-02-24 10:40:44 +08005772
5773 *mode = -1;
5774 // 0 use deny file, 1 use accept file
5775 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5776 *mode = (INT)strtol(buf, NULL, 10);
5777
5778 return RETURN_OK;
5779}
5780
developer06a01d92022-09-07 16:32:39 +08005781// adds the mac address to the filter list
5782//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5783INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5784{
5785 char cmd[MAX_CMD_SIZE]={'\0'};
5786 char buf[MAX_BUF_SIZE]={'\0'};
5787
developer2f995fb2023-02-24 10:40:44 +08005788 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005789 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005790
developer06a01d92022-09-07 16:32:39 +08005791 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5792 if(_syscmd(cmd,buf,sizeof(buf)))
5793 return RETURN_ERR;
5794
5795 return RETURN_OK;
5796}
5797
developer2f995fb2023-02-24 10:40:44 +08005798INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5799{
5800 char cmd[MAX_CMD_SIZE]={'\0'};
5801 char buf[MAX_BUF_SIZE]={'\0'};
5802
5803 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5804 return RETURN_ERR;
5805
5806 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5807 if(_syscmd(cmd,buf,sizeof(buf)))
5808 return RETURN_ERR;
5809
5810 return RETURN_OK;
5811}
5812
developer06a01d92022-09-07 16:32:39 +08005813// deletes the mac address from the filter list
5814//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5815INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5816{
5817 char cmd[MAX_CMD_SIZE]={'\0'};
5818 char buf[MAX_BUF_SIZE]={'\0'};
5819
5820#if 0
developerd946fd62022-12-08 18:03:28 +08005821 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005822 if(_syscmd(cmd,buf,sizeof(buf)))
5823 return RETURN_ERR;
5824
5825#endif
developer2f995fb2023-02-24 10:40:44 +08005826 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005827 if(_syscmd(cmd,buf,sizeof(buf)))
5828 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005829 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5830 if(_syscmd(cmd,buf,sizeof(buf)))
5831 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005832
5833 return RETURN_OK;
5834}
5835
5836// outputs the number of devices in the filter list
5837INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5838{
developere6aafda2022-09-13 14:59:28 +08005839 char cmd[MAX_BUF_SIZE]={0};
5840 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005841 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005842
5843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5844 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005845 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005846
developer2f995fb2023-02-24 10:40:44 +08005847 getAddressControlMode(apIndex, &mode);
5848 if (mode == -1)
5849 return RETURN_OK;
5850
5851 if (mode == 0)
5852 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5853 else if (mode == 1)
5854 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005855 _syscmd(cmd, buf, sizeof(buf));
5856
developer2f995fb2023-02-24 10:40:44 +08005857 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005858
5859 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5860 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005861}
5862
5863INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5864{
5865 char cmd[128]={'\0'};
5866 char buf[128]={'\0'};
5867
5868 if(strcmp(action,"DENY")==0)
5869 {
5870 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5871 system(buf);
5872 return RETURN_OK;
5873 }
5874
5875 if(strcmp(action,"ALLOW")==0)
5876 {
5877 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5878 system(buf);
5879 return RETURN_OK;
5880 }
5881
5882 return RETURN_ERR;
5883
5884}
5885
5886// enable kick for devices on acl black list
5887INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5888{
5889 char aclArray[512] = {0}, *acl = NULL;
5890 char assocArray[512] = {0}, *asso = NULL;
5891
developere6aafda2022-09-13 14:59:28 +08005892 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005893 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5894
5895 // if there are no devices connected there is nothing to do
5896 if (strlen(assocArray) < 17)
5897 return RETURN_OK;
5898
5899 if (enable == TRUE)
5900 {
5901 //kick off the MAC which is in ACL array (deny list)
5902 acl = strtok(aclArray, "\r\n");
5903 while (acl != NULL) {
5904 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5905 wifi_kickApAssociatedDevice(apIndex, acl);
5906
5907 acl = strtok(NULL, "\r\n");
5908 }
developere6aafda2022-09-13 14:59:28 +08005909 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005910 }
5911 else
5912 {
developere6aafda2022-09-13 14:59:28 +08005913 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005914 }
5915
5916#if 0
5917 //TODO: need to revisit below implementation
5918 char aclArray[512]={0}, *acl=NULL;
5919 char assocArray[512]={0}, *asso=NULL;
5920 char buf[256]={'\0'};
5921 char action[10]={'\0'};
5922 FILE *fr=NULL;
5923 char interface[10]={'\0'};
5924 char config_file[MAX_BUF_SIZE] = {0};
5925
5926 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5927 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5928 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5929 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5930
5931 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5932 system(buf);
5933 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5934 system(buf);
5935 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5936 system(buf);
5937 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5938 system(buf);
5939 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5940 system(buf);
5941
5942 if ( enable == TRUE )
5943 {
5944 int device_count=0;
5945 strcpy(action,"DENY");
5946 //kick off the MAC which is in ACL array (deny list)
5947 acl = strtok (aclArray,",");
5948 while (acl != NULL) {
5949 if(strlen(acl)>=17)
5950 {
5951 apply_rules(apIndex, acl,action,interface);
5952 device_count++;
5953 //Register mac to be blocked ,in syscfg.db persistent storage
5954 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5955 system(buf);
5956 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5957 system(buf);
5958 system("syscfg commit");
5959
5960 wifi_kickApAssociatedDevice(apIndex, acl);
5961 }
5962 acl = strtok (NULL, ",");
5963 }
5964 }
5965 else
5966 {
5967 int device_count=0;
5968 char cmdmac[20]={'\0'};
5969 strcpy(action,"ALLOW");
5970 //kick off the MAC which is not in ACL array (allow list)
5971 acl = strtok (aclArray,",");
5972 while (acl != NULL) {
5973 if(strlen(acl)>=17)
5974 {
5975 apply_rules(apIndex, acl,action,interface);
5976 device_count++;
5977 //Register mac to be Allowed ,in syscfg.db persistent storage
5978 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5979 system(buf);
5980 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5981 system(buf);
5982 sprintf(cmdmac,"%s",acl);
5983 }
5984 acl = strtok (NULL, ",");
5985 }
5986 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5987 system(buf);
5988
5989 //Disconnect the mac which is not in ACL
5990 asso = strtok (assocArray,",");
5991 while (asso != NULL) {
5992 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5993 wifi_kickApAssociatedDevice(apIndex, asso);
5994 asso = strtok (NULL, ",");
5995 }
5996 }
5997#endif
5998 return RETURN_OK;
5999}
6000
6001INT wifi_setPreferPrivateConnection(BOOL enable)
6002{
developer06a01d92022-09-07 16:32:39 +08006003 return RETURN_OK;
6004}
6005
6006// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
6007INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
6008{
developerd946fd62022-12-08 18:03:28 +08006009 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006010 int items = 1;
6011 struct params list[2];
6012 char buf[MAX_BUF_SIZE] = {0};
6013 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08006014 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08006015
6016 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08006017
developer10adcc12022-09-13 14:39:17 +08006018 if (filterMode == 0) {
6019 sprintf(buf, "%d", 0);
6020 list[0].value = buf;
6021
developer2f995fb2023-02-24 10:40:44 +08006022 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08006023 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006024 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08006025 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
6026 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006027 memset(cmd,0,sizeof(cmd));
6028 // Delete deny_mac_file in hostapd configuration
6029 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08006030 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006031 }
6032 else if (filterMode == 1) {
6033 sprintf(buf, "%d", filterMode);
6034 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08006035 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
6036 list[1].name = "accept_mac_file";
6037 list[1].value = acl_file;
6038 items = 2;
developer10adcc12022-09-13 14:39:17 +08006039 } else if (filterMode == 2) {
6040 //TODO: deny_mac_file
6041 sprintf(buf, "%d", 0);
6042 list[0].value = buf;
6043 list[1].name = "deny_mac_file";
6044 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
6045 list[1].value = deny_file;
6046 items = 2;
6047 } else {
6048 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006049 }
developer10adcc12022-09-13 14:39:17 +08006050
developer06a01d92022-09-07 16:32:39 +08006051 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6052 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08006053 if (multiple_set == FALSE) {
6054 wifi_setApEnable(apIndex, FALSE);
6055 wifi_setApEnable(apIndex, TRUE);
6056 }
developerefb790a2023-12-26 18:58:32 +08006057 snprintf(vap_info[apIndex].macaddr_acl, MAX_BUF_SIZE, "%s", list[0].value);
developer06a01d92022-09-07 16:32:39 +08006058
6059 return RETURN_OK;
6060
6061#if 0
6062 if(apIndex==0 || apIndex==1)
6063 {
6064 //set the filtermode
6065 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
6066 system(buf);
6067 system("syscfg commit");
6068
6069 if(filterMode==0)
6070 {
6071 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6072 system(buf);
6073 return RETURN_OK;
6074 }
6075 }
6076 return RETURN_OK;
6077#endif
6078}
6079
6080// 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.
6081INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6082{
6083 return RETURN_ERR;
6084}
6085
6086// gets the vlan ID for this ap from an internal enviornment variable
6087INT wifi_getApVlanID(INT apIndex, INT *output_int)
6088{
developer30423732022-12-01 16:17:49 +08006089 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08006090 {
6091 *output_int=100;
6092 return RETURN_OK;
6093 }
6094
6095 return RETURN_ERR;
6096}
6097
6098// sets the vlan ID for this ap to an internal enviornment variable
6099INT wifi_setApVlanID(INT apIndex, INT vlanId)
6100{
6101 //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)
6102 return RETURN_ERR;
6103}
6104
6105// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6106INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6107{
6108 snprintf(bridgeName, 32, "brlan0");
6109 snprintf(IP, 32, "10.0.0.1");
6110 snprintf(subnet, 32, "255.255.255.0");
6111
6112 return RETURN_OK;
6113}
6114
6115//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6116INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6117{
6118 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6119 return RETURN_ERR;
6120}
6121
6122// reset the vlan configuration for this ap
6123INT wifi_resetApVlanCfg(INT apIndex)
6124{
developerf5fef612022-09-20 19:38:26 +08006125 char original_config_file[64] = {0};
6126 char current_config_file[64] = {0};
6127 char buf[64] = {0};
6128 char cmd[64] = {0};
6129 char vlan_file[64] = {0};
6130 char vlan_tagged_interface[16] = {0};
6131 char vlan_bridge[16] = {0};
6132 char vlan_naming[16] = {0};
6133 struct params list[4] = {0};
6134 wifi_band band;
6135
6136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6137
6138 band = wifi_index_to_band(apIndex);
6139 if (band == band_2_4)
6140 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006141 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006142 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006143 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006144 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6145
6146 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6147
6148 if (strlen(vlan_file) == 0)
6149 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006150
developerf5fef612022-09-20 19:38:26 +08006151 // The file should exist or this vap would not work.
6152 if (access(vlan_file, F_OK) != 0) {
6153 sprintf(cmd, "touch %s", vlan_file);
6154 _syscmd(cmd, buf, sizeof(buf));
6155 }
6156 list[0].name = "vlan_file";
6157 list[0].value = vlan_file;
6158
6159 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6160 list[1].name = "vlan_tagged_interface";
6161 list[1].value = vlan_tagged_interface;
6162
6163 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6164 list[2].name = "vlan_bridge";
6165 list[2].value = vlan_bridge;
6166
6167 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6168 list[3].name = "vlan_naming";
6169 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006170
developerf5fef612022-09-20 19:38:26 +08006171 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6172 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006173 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006174 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006175
developerf5fef612022-09-20 19:38:26 +08006176 // restart this ap
6177 wifi_setApEnable(apIndex, FALSE);
6178 wifi_setApEnable(apIndex, TRUE);
6179
6180 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6181
6182 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006183}
6184
6185// 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.
6186INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6187{
6188 return RETURN_ERR;
6189}
6190
6191// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6192INT wifi_startHostApd()
6193{
6194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6195 system("systemctl start hostapd.service");
6196 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6197 return RETURN_OK;
6198 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6199}
6200
6201// stops hostapd
6202INT wifi_stopHostApd()
6203{
6204 char cmd[128] = {0};
6205 char buf[128] = {0};
6206
6207 sprintf(cmd,"systemctl stop hostapd");
6208 _syscmd(cmd, buf, sizeof(buf));
6209
6210 return RETURN_OK;
6211}
6212
6213// restart hostapd dummy function
6214INT wifi_restartHostApd()
6215{
6216 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6217 system("systemctl restart hostapd-global");
6218 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6219
6220 return RETURN_OK;
6221}
6222
6223static int align_hostapd_config(int index)
6224{
6225 ULONG lval;
6226 wifi_getRadioChannel(index%2, &lval);
6227 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006228 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006229}
6230
6231// sets the AP enable status variable for the specified ap.
6232INT wifi_setApEnable(INT apIndex, BOOL enable)
6233{
developerd946fd62022-12-08 18:03:28 +08006234 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006235 char config_file[MAX_BUF_SIZE] = {0};
6236 char cmd[MAX_CMD_SIZE] = {0};
6237 char buf[MAX_BUF_SIZE] = {0};
6238 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006239 int max_radio_num = 0;
6240 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006241
6242 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006243
6244 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006245 if (enable == status)
6246 return RETURN_OK;
6247
developerac6f1142022-12-20 19:26:35 +08006248 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006249 return RETURN_ERR;
6250
developer06a01d92022-09-07 16:32:39 +08006251 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006252 int radioIndex = apIndex % max_radio_num;
6253 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006254 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6255 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006256 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006257 _syscmd(cmd, buf, sizeof(buf));
developer2f18b9f2023-03-17 19:32:57 +08006258 if (!(apIndex/max_radio_num)) {
6259 sprintf(cmd, "iw %s del", interface_name);
6260 _syscmd(cmd, buf, sizeof(buf));
6261 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6262 _syscmd(cmd, buf, sizeof(buf));
6263 }
developer033b37b2022-10-18 11:27:46 +08006264 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006265 _syscmd(cmd, buf, sizeof(buf));
6266 }
6267 else {
developerd946fd62022-12-08 18:03:28 +08006268 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006269 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006270 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006271 _syscmd(cmd, buf, sizeof(buf));
6272 }
developera77d84b2023-02-22 16:10:50 +08006273
developer431128d2022-12-16 15:30:41 +08006274 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006275 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006276 _syscmd(cmd, buf, sizeof(buf));
6277 //Wait for wifi up/down to apply
6278 return RETURN_OK;
6279}
6280
6281// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6282INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6283{
developerd946fd62022-12-08 18:03:28 +08006284 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006285 char cmd[MAX_CMD_SIZE] = {'\0'};
6286 char buf[MAX_BUF_SIZE] = {'\0'};
6287
6288 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6289 return RETURN_ERR;
6290
6291 *output_bool = 0;
6292
6293 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6294 {
developerac6f1142022-12-20 19:26:35 +08006295 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006296 *output_bool = FALSE;
6297 return RETURN_OK;
6298 }
6299 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006300 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6301 }
6302
6303 return RETURN_OK;
6304}
6305
6306// Outputs the AP "Enabled" "Disabled" status from driver
6307INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6308{
6309 char cmd[128] = {0};
6310 char buf[128] = {0};
6311 BOOL output_bool;
6312
6313 if ( NULL == output_string)
6314 return RETURN_ERR;
6315 wifi_getApEnable(apIndex,&output_bool);
6316
6317 if(output_bool == 1)
6318 snprintf(output_string, 32, "Up");
6319 else
6320 snprintf(output_string, 32, "Disable");
6321
6322 return RETURN_OK;
6323}
6324
6325//Indicates whether or not beacons include the SSID name.
6326// outputs a 1 if SSID on the AP is enabled, else outputs 0
6327INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6328{
6329 //get the running status
6330 char config_file[MAX_BUF_SIZE] = {0};
6331 char buf[16] = {0};
6332
6333 if (!output)
6334 return RETURN_ERR;
6335
6336 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006337 if (!syn_flag)
6338 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6339 else
developer07ded1f2024-01-10 10:30:15 +08006340 snprintf(buf, sizeof(buf), "%s",vap_info[apIndex].ignore_broadcast_ssid);
developer1d57d002022-10-12 18:03:15 +08006341 // default is enable
6342 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6343 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006344
6345 return RETURN_OK;
6346}
6347
6348// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6349INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6350{
6351 //store the config, apply instantly
6352 char config_file[MAX_BUF_SIZE] = {0};
6353 struct params list;
6354
6355 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6356 list.name = "ignore_broadcast_ssid";
6357 list.value = enable?"0":"1";
6358
6359 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6360 wifi_hostapdWrite(config_file, &list, 1);
6361 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6362 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006363 wifi_reloadAp(apIndex);
developerefb790a2023-12-26 18:58:32 +08006364 snprintf(vap_info[apIndex].ignore_broadcast_ssid, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08006365 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6366
6367 return RETURN_OK;
6368}
6369
6370//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6371INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6372{
6373 //get the running status
6374 if(!output_uint)
6375 return RETURN_ERR;
6376 *output_uint=16;
6377 return RETURN_OK;
6378}
6379
6380INT wifi_setApRetryLimit(INT apIndex, UINT number)
6381{
6382 //apply instantly
6383 return RETURN_ERR;
6384}
6385
6386//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6387INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6388{
6389 if(!output)
6390 return RETURN_ERR;
6391 *output=TRUE;
6392 return RETURN_OK;
6393}
6394
6395//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6396INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6397{
6398 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006399 char cmd[128] = {0};
6400 char buf[128] = {0};
6401 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006402 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006403
developer0b246d12022-09-30 15:24:20 +08006404 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006405
developer0b246d12022-09-30 15:24:20 +08006406 wifi_getMaxRadioNumber(&max_radio_num);
6407 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006408 phyId = radio_index_to_phy(radioIndex);
6409 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006410 _syscmd(cmd,buf, sizeof(buf));
6411
6412 if (strlen(buf) > 0)
6413 *output = true;
6414
6415 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006416
developer06a01d92022-09-07 16:32:39 +08006417 return RETURN_OK;
6418}
6419
6420//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6421INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6422{
6423 //get the running status from driver
6424 if(!output)
6425 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006426
6427 char config_file[MAX_BUF_SIZE] = {0};
6428 char buf[16] = {0};
6429
6430 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6431 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006432 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006433 *output = TRUE;
6434 else
6435 *output = FALSE;
6436
developer06a01d92022-09-07 16:32:39 +08006437 return RETURN_OK;
6438}
6439
6440// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6441INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6442{
6443 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006444 char config_file[MAX_BUF_SIZE] = {0};
6445 struct params list;
6446
6447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6448 list.name = "wmm_enabled";
6449 list.value = enable?"1":"0";
6450
6451 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6452 wifi_hostapdWrite(config_file, &list, 1);
6453 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6454 wifi_reloadAp(apIndex);
6455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6456
6457 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006458}
6459
6460//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.
6461INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6462{
6463 //get the running status from driver
6464 if(!output)
6465 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006466
6467 char config_file[128] = {0};
6468 char buf[16] = {0};
6469
6470 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6471 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6472 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6473 *output = TRUE;
6474 else
6475 *output = FALSE;
6476
developer06a01d92022-09-07 16:32:39 +08006477 return RETURN_OK;
6478}
6479
6480// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6481INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6482{
6483 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006484 char config_file[MAX_BUF_SIZE] = {0};
6485 struct params list;
6486
6487 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6488 list.name = "uapsd_advertisement_enabled";
6489 list.value = enable?"1":"0";
6490
6491 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6492 wifi_hostapdWrite(config_file, &list, 1);
6493 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6494 wifi_reloadAp(apIndex);
6495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6496
6497 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006498}
6499
developer6daeb3f2022-09-30 13:36:39 +08006500// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006501INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6502{
developerd946fd62022-12-08 18:03:28 +08006503 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006504 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6505 char cmd[128] = {0};
6506 char buf[128] = {0};
6507 char ack_filepath[128] = {0};
6508 uint16_t bitmap = 0;
6509 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6510 FILE *f = NULL;
6511
6512 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6513
6514 // Get current setting
6515 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6516 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6517 _syscmd(cmd, buf, sizeof(buf));
6518 if (strlen(buf) > 0)
6519 bitmap = strtoul(buf, NULL, 10);
6520
6521 bitmap = strtoul(buf, NULL, 10);
6522
6523 if (ackPolicy == TRUE) { // True, unset this class
6524 bitmap &= ~class_map[class];
6525 } else { // False, set this class
6526 bitmap |= class_map[class];
6527 }
6528
6529 f = fopen(ack_filepath, "w");
6530 if (f == NULL) {
6531 fprintf(stderr, "%s: fopen failed\n", __func__);
6532 return RETURN_ERR;
6533 }
6534 fprintf(f, "%hu", bitmap);
6535 fclose(f);
6536
developerac6f1142022-12-20 19:26:35 +08006537 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006538 return RETURN_ERR;
6539 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006540 _syscmd(cmd, buf, sizeof(buf));
6541
6542 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6543 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006544}
6545
6546//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.
6547INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6548{
6549 //get the running status from driver
6550 if(!output_uint)
6551 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006552
6553 char output[16]={'\0'};
6554 char config_file[MAX_BUF_SIZE] = {0};
6555
6556 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006557 if (!syn_flag)
6558 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6559 else
developer07ded1f2024-01-10 10:30:15 +08006560 snprintf(output, sizeof(output), "%s", vap_info[apIndex].max_sta);
developer0947e1a2022-09-13 14:15:25 +08006561 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6562 else {
6563 int device_num = atoi(output);
6564 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6565 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6566 return RETURN_ERR;
6567 }
6568 else {
6569 *output_uint = device_num;
6570 }
6571 }
6572
developer06a01d92022-09-07 16:32:39 +08006573 return RETURN_OK;
6574}
6575
6576INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6577{
6578 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006579 char str[MAX_BUF_SIZE]={'\0'};
6580 char cmd[MAX_CMD_SIZE]={'\0'};
6581 struct params params;
6582 char config_file[MAX_BUF_SIZE] = {0};
6583
6584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006585 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006586 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006587 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006588 }
6589 sprintf(str, "%d", number);
6590 params.name = "max_num_sta";
6591 params.value = str;
6592
6593 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6594 int ret = wifi_hostapdWrite(config_file, &params, 1);
6595 if (ret) {
6596 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6597 ,__func__, ret);
6598 }
6599
6600 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6601 if (ret) {
6602 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6603 ,__func__, ret);
6604 }
6605 wifi_reloadAp(apIndex);
6606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6607
6608 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006609}
6610
6611//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.
6612INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6613{
6614 //get the current threshold
6615 if(!output_uint)
6616 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006617 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6618 if (*output_uint == 0)
6619 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006620 return RETURN_OK;
6621}
6622
6623INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6624{
6625 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006626 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6627 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006628 return RETURN_ERR;
6629}
6630
6631//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.
6632INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(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//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6641INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6642{
6643 if(!output_uint)
6644 return RETURN_ERR;
6645 *output_uint = 3;
6646 return RETURN_OK;
6647}
6648
6649//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.
6650INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6651{
6652 if(!output_in_seconds)
6653 return RETURN_ERR;
6654 *output_in_seconds = 0;
6655 return RETURN_OK;
6656}
6657
6658//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
6659INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6660{
6661 if(!output || apIndex>=MAX_APS)
6662 return RETURN_ERR;
6663 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006664 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006665 return RETURN_OK;
6666}
6667
6668//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6669INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6670{
developer587c1b62022-09-27 15:58:59 +08006671 char config_file[128] = {0};
6672 char wpa[16] = {0};
6673 char key_mgmt[64] = {0};
6674 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006675 if (!output)
6676 return RETURN_ERR;
6677
6678 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006679 if (!syn_flag)
6680 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6681 else
developer07ded1f2024-01-10 10:30:15 +08006682 snprintf(wpa, sizeof(wpa), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006683
developer587c1b62022-09-27 15:58:59 +08006684 strcpy(output, "None");//Copying "None" to output string for default case
developerefb790a2023-12-26 18:58:32 +08006685 if (!syn_flag)
6686 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6687 else
developer07ded1f2024-01-10 10:30:15 +08006688 snprintf(key_mgmt, sizeof(key_mgmt), "%s", vap_info[apIndex].wpa_key_mgmt);
developer4a359672022-10-13 15:30:46 +08006689 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006690 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006691 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006692 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006693 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006694 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006695 snprintf(output, 32, "WPA-WPA2-Personal");
6696
developer72ec5572023-01-05 16:27:13 +08006697 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6698 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006699 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006700 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006701 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006702 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006703 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006704 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006705 snprintf(output, 32, "WPA-WPA2-Enterprise");
6706 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006707 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006708 snprintf(output, 32, "WPA3-Personal");
6709 else
developer4a359672022-10-13 15:30:46 +08006710 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006711 }
developer06a01d92022-09-07 16:32:39 +08006712
6713 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6714 return RETURN_OK;
6715#if 0
6716 //TODO: need to revisit below implementation
6717 char securityType[32], authMode[32];
6718 int enterpriseMode=0;
6719
6720 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6721 if(!output)
6722 return RETURN_ERR;
6723
6724 wifi_getApBeaconType(apIndex, securityType);
6725 strcpy(output,"None");//By default, copying "None" to output string
6726 if (strncmp(securityType,"None", strlen("None")) == 0)
6727 return RETURN_OK;
6728
6729 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6730 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6731
6732 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6733 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6734 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6735 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6736 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6737 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6738 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6739
6740 return RETURN_OK;
6741#endif
6742}
6743
6744INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6745{
6746 char securityType[32];
6747 char authMode[32];
6748
6749 //store settings and wait for wifi up to apply
6750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6751 if(!encMode)
6752 return RETURN_ERR;
6753
developer06a01d92022-09-07 16:32:39 +08006754 if (strcmp(encMode, "None")==0)
6755 {
6756 strcpy(securityType,"None");
6757 strcpy(authMode,"None");
6758 }
6759 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6760 {
6761 strcpy(securityType,"WPAand11i");
6762 strcpy(authMode,"PSKAuthentication");
6763 }
6764 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6765 {
6766 strcpy(securityType,"WPAand11i");
6767 strcpy(authMode,"EAPAuthentication");
6768 }
6769 else if (strcmp(encMode, "WPA-Personal")==0)
6770 {
6771 strcpy(securityType,"WPA");
6772 strcpy(authMode,"PSKAuthentication");
6773 }
6774 else if (strcmp(encMode, "WPA-Enterprise")==0)
6775 {
6776 strcpy(securityType,"WPA");
6777 strcpy(authMode,"EAPAuthentication");
6778 }
6779 else if (strcmp(encMode, "WPA2-Personal")==0)
6780 {
6781 strcpy(securityType,"11i");
6782 strcpy(authMode,"PSKAuthentication");
6783 }
6784 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6785 {
6786 strcpy(securityType,"11i");
6787 strcpy(authMode,"EAPAuthentication");
6788 }
developer587c1b62022-09-27 15:58:59 +08006789 else if (strcmp(encMode, "WPA3-Personal") == 0)
6790 {
6791 strcpy(securityType,"11i");
6792 strcpy(authMode,"SAEAuthentication");
6793 }
developer4a359672022-10-13 15:30:46 +08006794 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006795 {
6796 strcpy(securityType, "11i");
6797 strcpy(authMode, "PSK-SAEAuthentication");
6798 }
developer587c1b62022-09-27 15:58:59 +08006799 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6800 {
6801 strcpy(securityType,"11i");
6802 strcpy(authMode,"EAP_192-bit_Authentication");
6803 }
developer5c9fee82023-01-13 14:44:16 +08006804 else if (strcmp(encMode, "OWE") == 0)
6805 {
6806 strcpy(securityType,"11i");
6807 strcpy(authMode,"Enhanced_Open");
6808 }
developer06a01d92022-09-07 16:32:39 +08006809 else
6810 {
6811 strcpy(securityType,"None");
6812 strcpy(authMode,"None");
6813 }
6814 wifi_setApBeaconType(apIndex, securityType);
6815 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6816 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6817
6818 return RETURN_OK;
6819}
6820
6821
developer4b102122023-02-15 10:53:03 +08006822// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006823//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006824INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6825{
developer30423732022-12-01 16:17:49 +08006826 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006827 char config_file[MAX_BUF_SIZE] = {0};
6828
6829 if(output_string==NULL)
6830 return RETURN_ERR;
6831
6832 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006833 if (!syn_flag)
6834 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6835 else
developer07ded1f2024-01-10 10:30:15 +08006836 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006837 if(strcmp(buf,"0")==0)
6838 {
6839 printf("wpa_mode is %s ......... \n",buf);
6840 return RETURN_ERR;
6841 }
6842
6843 wifi_dbg_printf("\nFunc=%s\n",__func__);
6844 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006845 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006846 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6847
6848 return RETURN_OK;
6849}
6850
developer4b102122023-02-15 10:53:03 +08006851// Set PreSharedKey associated with a Access Point.
6852// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006853INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6854{
6855 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6856 struct params params={'\0'};
6857 int ret;
6858 char config_file[MAX_BUF_SIZE] = {0};
6859
6860 if(NULL == preSharedKey)
6861 return RETURN_ERR;
6862
developer4b102122023-02-15 10:53:03 +08006863 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006864
developer4b102122023-02-15 10:53:03 +08006865 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006866 {
developer4b102122023-02-15 10:53:03 +08006867 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006868 return RETURN_ERR;
6869 }
6870 params.value = preSharedKey;
6871 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6872 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006873 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006874 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006875 wifi_reloadAp(apIndex);
6876 }
developer06a01d92022-09-07 16:32:39 +08006877 return ret;
6878 //TODO: call hostapd_cli for dynamic_config_control
6879}
6880
6881//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6882// outputs the passphrase, maximum 63 characters
6883INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6884{
6885 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6886
6887 wifi_dbg_printf("\nFunc=%s\n",__func__);
6888 if (NULL == output_string)
6889 return RETURN_ERR;
6890
6891 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006892 if (!syn_flag)
6893 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6894 else
developer07ded1f2024-01-10 10:30:15 +08006895 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006896 if(strcmp(buf,"0")==0)
6897 {
6898 printf("wpa_mode is %s ......... \n",buf);
6899 return RETURN_ERR;
6900 }
6901
developerefb790a2023-12-26 18:58:32 +08006902 if (!syn_flag)
6903 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6904 else
developer07ded1f2024-01-10 10:30:15 +08006905 snprintf(output_string, 64, "%s", vap_info[apIndex].wpa_passphrase);
developer06a01d92022-09-07 16:32:39 +08006906 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6907
6908 return RETURN_OK;
6909}
6910
6911// sets the passphrase enviornment variable, max 63 characters
6912INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6913{
6914 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6915 struct params params={'\0'};
6916 char config_file[MAX_BUF_SIZE] = {0};
6917 int ret;
6918
6919 if(NULL == passPhrase)
6920 return RETURN_ERR;
6921
6922 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6923 {
6924 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6925 return RETURN_ERR;
6926 }
6927 params.name = "wpa_passphrase";
6928 params.value = passPhrase;
6929 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6930 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006931 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006932 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006933 wifi_reloadAp(apIndex);
6934 }
developerefb790a2023-12-26 18:58:32 +08006935 snprintf(vap_info[apIndex].wpa_passphrase, MAX_BUF_SIZE, "%s", passPhrase);
developer06a01d92022-09-07 16:32:39 +08006936
6937 return ret;
6938}
6939
6940//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.
6941INT wifi_setApSecurityReset(INT apIndex)
6942{
developer8d583982022-09-20 11:28:22 +08006943 char original_config_file[64] = {0};
6944 char current_config_file[64] = {0};
6945 char buf[64] = {0};
6946 char cmd[64] = {0};
6947 char wpa[4] = {0};
6948 char wpa_psk[64] = {0};
6949 char wpa_passphrase[64] = {0};
6950 char wpa_psk_file[128] = {0};
6951 char wpa_key_mgmt[64] = {0};
6952 char wpa_pairwise[32] = {0};
6953 wifi_band band;
6954 struct params list[6];
6955
6956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6957
6958 band = wifi_index_to_band(apIndex);
6959 if (band == band_2_4)
6960 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006961 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006962 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006963 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006964 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6965 else
6966 return RETURN_ERR;
6967
6968 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6969 list[0].name = "wpa";
6970 list[0].value = wpa;
6971
6972 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6973 list[1].name = "wpa_psk";
6974 list[1].value = wpa_psk;
6975
6976 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6977 list[2].name = "wpa_passphrase";
6978 list[2].value = wpa_passphrase;
6979
6980 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6981
6982 if (strlen(wpa_psk_file) == 0)
6983 strcpy(wpa_psk_file, PSK_FILE);
6984
6985 if (access(wpa_psk_file, F_OK) != 0) {
6986 sprintf(cmd, "touch %s", wpa_psk_file);
6987 _syscmd(cmd, buf, sizeof(buf));
6988 }
6989 list[3].name = "wpa_psk_file";
6990 list[3].value = wpa_psk_file;
6991
6992 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6993 list[4].name = "wpa_key_mgmt";
6994 list[4].value = wpa_key_mgmt;
6995
6996 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6997 list[5].name = "wpa_pairwise";
6998 list[5].value = wpa_pairwise;
6999
7000 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7001 wifi_hostapdWrite(current_config_file, list, 6);
7002
7003 wifi_setApEnable(apIndex, FALSE);
7004 wifi_setApEnable(apIndex, TRUE);
7005
7006 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7007 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007008}
7009
7010//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).
7011INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7012{
developer8f2ddd52022-09-13 15:39:24 +08007013 char config_file[64] = {0};
7014 char buf[64] = {0};
7015 char cmd[256] = {0};
7016
7017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7018
developer06a01d92022-09-07 16:32:39 +08007019 if(!IP_output || !Port_output || !RadiusSecret_output)
7020 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08007021
developer8f2ddd52022-09-13 15:39:24 +08007022 // Read the first matched config
7023 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7024 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7025 _syscmd(cmd, buf, sizeof(buf));
7026 strncpy(IP_output, buf, 64);
7027
7028 memset(buf, 0, sizeof(buf));
7029 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7030 _syscmd(cmd, buf, sizeof(buf));
7031 *Port_output = atoi(buf);
7032
7033 memset(buf, 0, sizeof(buf));
7034 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7035 _syscmd(cmd, buf, sizeof(buf));
7036 strncpy(RadiusSecret_output, buf, 64);
7037
7038 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007039 return RETURN_OK;
7040}
7041
7042INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7043{
developer8f2ddd52022-09-13 15:39:24 +08007044 char config_file[64] = {0};
7045 char port_str[8] = {0};
7046 char cmd[256] = {0};
7047 char buf[128] = {0};
7048
7049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007050 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7051 return RETURN_ERR;
7052
7053 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7054 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007055
7056 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7057
7058 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7059 _syscmd(cmd, buf, sizeof(buf));
7060 memset(cmd, 0, sizeof(cmd));
7061
7062 snprintf(port_str, sizeof(port_str), "%d", port);
7063 if (strlen(buf) == 0)
7064 // Append
7065 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7066 "auth_server_addr=%s\\n"
7067 "auth_server_port=%s\\n"
7068 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7069 else {
7070 // Delete the three lines setting after the "# radius 1" comment
7071 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7072 _syscmd(cmd, buf, sizeof(buf));
7073 memset(cmd, 0, sizeof(cmd));
7074 // Use "# radius 1" comment to find the location to insert the radius setting
7075 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7076 "# radius 1\\n"
7077 "auth_server_addr=%s\\n"
7078 "auth_server_port=%s\\n"
7079 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7080 }
7081 if(_syscmd(cmd, buf, sizeof(buf))) {
7082 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7083 return RETURN_ERR;
7084 }
7085
7086 wifi_reloadAp(apIndex);
7087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7088 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007089}
7090
7091INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7092{
developer8f2ddd52022-09-13 15:39:24 +08007093 char config_file[64] = {0};
7094 char buf[64] = {0};
7095 char cmd[256] = {0};
7096
7097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7098
developer06a01d92022-09-07 16:32:39 +08007099 if(!IP_output || !Port_output || !RadiusSecret_output)
7100 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007101
7102 // Read the second matched config
7103 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7104 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7105 _syscmd(cmd, buf, sizeof(buf));
7106 strncpy(IP_output, buf, 64);
7107
7108 memset(buf, 0, sizeof(buf));
7109 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7110 _syscmd(cmd, buf, sizeof(buf));
7111 *Port_output = atoi(buf);
7112
7113 memset(buf, 0, sizeof(buf));
7114 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7115 _syscmd(cmd, buf, sizeof(buf));
7116 strncpy(RadiusSecret_output, buf, 64);
7117
7118 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007119 return RETURN_OK;
7120}
7121
7122INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7123{
developer8f2ddd52022-09-13 15:39:24 +08007124 char config_file[64] = {0};
7125 char port_str[8] = {0};
7126 char cmd[256] = {0};
7127 char buf[128] = {0};
7128
7129 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007130 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7131 return RETURN_ERR;
7132
7133 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7134 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007135
7136 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7137
7138 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7139 _syscmd(cmd, buf, sizeof(buf));
7140 memset(cmd, 0, sizeof(cmd));
7141
7142 snprintf(port_str, sizeof(port_str), "%d", port);
7143 if (strlen(buf) == 0)
7144 // Append
7145 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7146 "auth_server_addr=%s\\n"
7147 "auth_server_port=%s\\n"
7148 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7149 else {
7150 // Delete the three lines setting after the "# radius 2" comment
7151 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7152 _syscmd(cmd, buf, sizeof(buf));
7153 memset(cmd, 0, sizeof(cmd));
7154 // Use "# radius 2" comment to find the location to insert the radius setting
7155 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7156 "# radius 2\\n"
7157 "auth_server_addr=%s\\n"
7158 "auth_server_port=%s\\n"
7159 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7160 }
7161 if(_syscmd(cmd, buf, sizeof(buf))) {
7162 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7163 return RETURN_ERR;
7164 }
7165
7166 wifi_reloadAp(apIndex);
7167 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7168 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007169}
7170
7171//RadiusSettings
7172INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7173{
7174 if(!output)
7175 return RETURN_ERR;
7176
7177 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7178 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7179 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7180 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7181 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7182 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.
7183 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7184 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7185 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7186 //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.
7187
7188 return RETURN_OK;
7189}
7190
7191INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7192{
7193 //store the paramters, and apply instantly
7194 return RETURN_ERR;
7195}
7196
7197//Device.WiFi.AccessPoint.{i}.WPS.Enable
7198//Enables or disables WPS functionality for this access point.
7199// outputs the WPS enable state of this ap in output_bool
7200INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7201{
developerd946fd62022-12-08 18:03:28 +08007202 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007203 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer613892e2023-09-21 16:33:35 +08007204
7205 *output_bool=FALSE;
developer5b398df2022-11-17 20:39:48 +08007206 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007207 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007208 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer613892e2023-09-21 16:33:35 +08007209 return RETURN_OK;
developerd946fd62022-12-08 18:03:28 +08007210 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007211 _syscmd(cmd, buf, sizeof(buf));
7212 if(strstr(buf, "configured"))
7213 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08007214
7215 return RETURN_OK;
developer613892e2023-09-21 16:33:35 +08007216}
developer06a01d92022-09-07 16:32:39 +08007217
7218//Device.WiFi.AccessPoint.{i}.WPS.Enable
7219// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7220INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7221{
7222 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007223 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007224 struct params params;
7225
developer06a01d92022-09-07 16:32:39 +08007226 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7227 //store the paramters, and wait for wifi up to apply
7228 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007229 if (enable == TRUE) {
7230 wifi_getApBeaconType(apIndex, buf);
7231 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7232 params.value = "1";
7233 else // If ap set encryption
7234 params.value = "2";
7235 } else {
7236 params.value = "0";
7237 }
developer06a01d92022-09-07 16:32:39 +08007238
7239 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7240 wifi_hostapdWrite(config_file, &params, 1);
7241 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7242 wifi_reloadAp(apIndex);
7243
7244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7245 return RETURN_OK;
7246}
7247
7248//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
7249INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7250{
7251 if(!output)
7252 return RETURN_ERR;
7253 snprintf(output, 128, "PushButton,PIN");
7254 return RETURN_OK;
7255}
7256
7257//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7258//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.
7259// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7260INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7261{
7262 if(!output)
7263 return RETURN_ERR;
7264 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7265
7266 return RETURN_OK;
7267}
7268
7269//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7270// 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
7271INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7272{
7273 //apply instantly. No setting need to be stored.
7274 char methods[MAX_BUF_SIZE], *token, *next_token;
7275 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7276 struct params params;
7277
developer5b398df2022-11-17 20:39:48 +08007278 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007279 return RETURN_ERR;
7280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7281 //store the paramters, and wait for wifi up to apply
7282
7283 snprintf(methods, sizeof(methods), "%s", methodString);
7284 for(token=methods; *token; token=next_token)
7285 {
7286 strtok_r(token, ",", &next_token);
7287 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7288 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7289 else if(*token=='E')
7290 {
7291 if(!strcmp(methods, "Ethernet"))
7292 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7293 else if(!strcmp(methods, "ExternalNFCToken"))
7294 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7295 else
7296 printf("%s: Unknown WpsConfigMethod\n", __func__);
7297 }
7298 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7299 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7300 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7301 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7302 else if(*token=='P' )
7303 {
7304 if(!strcmp(token, "PushButton"))
developer894affa2023-05-10 18:13:19 +08007305 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer06a01d92022-09-07 16:32:39 +08007306 else if(!strcmp(token, "PIN"))
7307 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7308 else
7309 printf("%s: Unknown WpsConfigMethod\n", __func__);
7310 }
7311 else
7312 printf("%s: Unknown WpsConfigMethod\n", __func__);
7313 }
7314 params.name = "config_methods";
7315 params.value = config_methods;
7316 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7317 wifi_hostapdWrite(config_file, &params, 1);
7318 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7319 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7320
7321 return RETURN_OK;
7322}
7323
7324// outputs the pin value, ulong_pin must be allocated by the caller
7325INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7326{
7327 char buf[MAX_BUF_SIZE] = {0};
7328 char cmd[MAX_CMD_SIZE] = {0};
7329
developer5b398df2022-11-17 20:39:48 +08007330 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007331 return RETURN_ERR;
7332 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7333 _syscmd(cmd, buf, sizeof(buf));
7334 if(strlen(buf) > 0)
7335 *output_ulong=strtoul(buf, NULL, 10);
7336
7337 return RETURN_OK;
7338}
7339
7340// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7341INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7342{
7343 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7344 char ap_pin[16] = {0};
7345 char buf[MAX_BUF_SIZE] = {0};
7346 char config_file[MAX_BUF_SIZE] = {0};
7347 ULONG prev_pin = 0;
7348 struct params params;
7349
developer06a01d92022-09-07 16:32:39 +08007350 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7351 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7352 params.name = "ap_pin";
7353 params.value = ap_pin;
7354 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7355 wifi_hostapdWrite(config_file, &params, 1);
7356 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7358
7359 return RETURN_OK;
7360}
7361
7362// Output string is either Not configured or Configured, max 32 characters
7363INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7364{
developerd946fd62022-12-08 18:03:28 +08007365 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007366 char cmd[MAX_CMD_SIZE];
7367 char buf[MAX_BUF_SIZE]={0};
7368
developer5b398df2022-11-17 20:39:48 +08007369 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007370 return RETURN_ERR;
7371 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7372 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007373 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007374 return RETURN_ERR;
7375 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007376 _syscmd(cmd, buf, sizeof(buf));
7377
developer348e3d92022-09-13 14:48:41 +08007378 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007379 snprintf(output_string, 32, "Configured");
7380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7381
7382 return RETURN_OK;
7383}
7384
7385// sets the WPS pin for this AP
7386INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7387{
developerd946fd62022-12-08 18:03:28 +08007388 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007389 char cmd[MAX_CMD_SIZE];
7390 char buf[MAX_BUF_SIZE]={0};
7391 BOOL enable;
7392
developer06a01d92022-09-07 16:32:39 +08007393 wifi_getApEnable(apIndex, &enable);
7394 if (!enable)
7395 return RETURN_ERR;
7396 wifi_getApWpsEnable(apIndex, &enable);
7397 if (!enable)
7398 return RETURN_ERR;
7399
developerac6f1142022-12-20 19:26:35 +08007400 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007401 return RETURN_ERR;
7402 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007403 _syscmd(cmd, buf, sizeof(buf));
7404 if((strstr(buf, "OK"))!=NULL)
7405 return RETURN_OK;
7406
7407 return RETURN_ERR;
7408}
7409
7410// This function is called when the WPS push button has been pressed for this AP
7411INT wifi_setApWpsButtonPush(INT apIndex)
7412{
7413 char cmd[MAX_CMD_SIZE];
7414 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007415 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007416 BOOL enable=FALSE;
7417
developer06a01d92022-09-07 16:32:39 +08007418 wifi_getApEnable(apIndex, &enable);
7419 if (!enable)
7420 return RETURN_ERR;
7421
7422 wifi_getApWpsEnable(apIndex, &enable);
7423 if (!enable)
7424 return RETURN_ERR;
7425
developerac6f1142022-12-20 19:26:35 +08007426 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007427 return RETURN_ERR;
7428
developer900e2b72023-05-23 10:23:48 +08007429 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 +08007430 _syscmd(cmd, buf, sizeof(buf));
7431
7432 if((strstr(buf, "OK"))!=NULL)
7433 return RETURN_OK;
7434 return RETURN_ERR;
7435}
7436
7437// cancels WPS mode for this AP
7438INT wifi_cancelApWPS(INT apIndex)
7439{
developerd946fd62022-12-08 18:03:28 +08007440 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007441 char cmd[MAX_CMD_SIZE];
7442 char buf[MAX_BUF_SIZE]={0};
7443
developerac6f1142022-12-20 19:26:35 +08007444 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007445 return RETURN_ERR;
7446 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007447 _syscmd(cmd,buf, sizeof(buf));
7448
7449 if((strstr(buf, "OK"))!=NULL)
7450 return RETURN_OK;
7451 return RETURN_ERR;
7452}
7453
7454//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7455//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7456INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7457{
developerd946fd62022-12-08 18:03:28 +08007458 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007459 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007460 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007461 char cmd[256] = {0}, buf[2048] = {0};
7462 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007463 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007464 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007465 wifi_associated_dev_t *dev=NULL;
7466
7467 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7468 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007469 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007470 return RETURN_ERR;
7471 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007472 _syscmd(cmd,buf,sizeof(buf));
7473 *output_array_size = atoi(buf);
7474
7475 if (*output_array_size <= 0)
7476 return RETURN_OK;
7477
7478 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7479 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007480 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007481 _syscmd(cmd,buf,sizeof(buf));
7482 f = fopen("/tmp/connected_devices.txt", "r");
7483 if (f==NULL)
7484 {
7485 *output_array_size=0;
7486 return RETURN_ERR;
7487 }
developer30423732022-12-01 16:17:49 +08007488 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007489 {
7490 param = strtok(line,"=");
7491 value = strtok(NULL,"=");
7492
7493 if( strcmp("flags",param) == 0 )
7494 {
7495 value[strlen(value)-1]='\0';
7496 if(strstr (value,"AUTHORIZED") != NULL )
7497 {
7498 dev[auth_temp].cli_AuthenticationState = 1;
7499 dev[auth_temp].cli_Active = 1;
7500 auth_temp++;
7501 read_flag=1;
7502 }
7503 }
7504 if(read_flag==1)
7505 {
7506 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7507 {
7508 value[strlen(value)-1]='\0';
7509 sscanf(value, "%x:%x:%x:%x:%x:%x",
7510 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7511 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7512 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7513 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7514 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7515 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7516 mac_temp++;
7517 read_flag=0;
7518 }
7519 }
7520 }
7521 *output_array_size = auth_temp;
7522 auth_temp=0;
7523 mac_temp=0;
7524 free(line);
7525 fclose(f);
7526 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7527 return RETURN_OK;
7528}
7529
7530#define MACADDRESS_SIZE 6
7531
7532INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7533{
7534 FILE *fp = NULL;
7535 char str[MAX_BUF_SIZE] = {0};
7536 int wificlientindex = 0 ;
7537 int count = 0;
7538 int signalstrength = 0;
7539 int arr[MACADDRESS_SIZE] = {0};
7540 unsigned char mac[MACADDRESS_SIZE] = {0};
7541 UINT wifi_count = 0;
7542 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7543 char pipeCmd[MAX_CMD_SIZE] = {0};
7544
7545 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7546 *output_array_size = 0;
7547 *associated_dev_array = NULL;
7548
7549 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7550 fp = popen(pipeCmd, "r");
7551 if (fp == NULL)
7552 {
7553 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7554 return RETURN_ERR;
7555 }
7556
7557 /* Read the output a line at a time - output it. */
7558 fgets(str, sizeof(str)-1, fp);
7559 wifi_count = (unsigned int) atoi ( str );
7560 *output_array_size = wifi_count;
7561 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7562 pclose(fp);
7563
7564 if(wifi_count == 0)
7565 {
7566 return RETURN_OK;
7567 }
7568 else
7569 {
7570 wifi_associated_dev3_t* temp = NULL;
7571 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7572 if(temp == NULL)
7573 {
7574 printf("Error Statement. Insufficient memory \n");
7575 return RETURN_ERR;
7576 }
7577
7578 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7579 system(pipeCmd);
7580 memset(pipeCmd,0,sizeof(pipeCmd));
7581 if(apIndex == 0)
7582 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7583 else if(apIndex == 1)
7584 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7585 system(pipeCmd);
7586
7587 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7588 if(fp == NULL)
7589 {
7590 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007591 free(temp);
developer06a01d92022-09-07 16:32:39 +08007592 return RETURN_ERR;
7593 }
7594 fclose(fp);
7595
developer30423732022-12-01 16:17:49 +08007596 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007597 fp = popen(pipeCmd, "r");
7598 if(fp)
7599 {
7600 for(count =0 ; count < wifi_count; count++)
7601 {
7602 fgets(str, MAX_BUF_SIZE, fp);
7603 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7604 {
7605 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7606 {
7607 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7608
7609 }
7610 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7611 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]);
7612 }
7613 temp[count].cli_AuthenticationState = 1; //TODO
7614 temp[count].cli_Active = 1; //TODO
7615 }
7616 pclose(fp);
7617 }
7618
developer30423732022-12-01 16:17:49 +08007619 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 +08007620 fp = popen(pipeCmd, "r");
7621 if(fp)
7622 {
7623 pclose(fp);
7624 }
7625 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7626 if(fp)
7627 {
7628 for(count =0 ; count < wifi_count ;count++)
7629 {
7630 fgets(str, MAX_BUF_SIZE, fp);
7631 signalstrength = atoi(str);
7632 temp[count].cli_SignalStrength = signalstrength;
7633 temp[count].cli_RSSI = signalstrength;
7634 temp[count].cli_SNR = signalstrength + 95;
7635 }
7636 pclose(fp);
7637 }
7638
7639
7640 if((apIndex == 0) || (apIndex == 4))
7641 {
7642 for(count =0 ; count < wifi_count ;count++)
7643 {
7644 strcpy(temp[count].cli_OperatingStandard,"g");
7645 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7646 }
7647
7648 //BytesSent
developer30423732022-12-01 16:17:49 +08007649 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 +08007650 fp = popen(pipeCmd, "r");
7651 if(fp)
7652 {
7653 pclose(fp);
7654 }
7655 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7656 if(fp)
7657 {
7658 for (count = 0; count < wifi_count; count++)
7659 {
7660 fgets(str, MAX_BUF_SIZE, fp);
7661 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7662 }
7663 pclose(fp);
7664 }
7665
7666 //BytesReceived
developer30423732022-12-01 16:17:49 +08007667 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 +08007668 fp = popen(pipeCmd, "r");
7669 if (fp)
7670 {
7671 pclose(fp);
7672 }
7673 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7674 if (fp)
7675 {
7676 for (count = 0; count < wifi_count; count++)
7677 {
7678 fgets(str, MAX_BUF_SIZE, fp);
7679 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7680 }
7681 pclose(fp);
7682 }
7683
7684 //PacketsSent
developer30423732022-12-01 16:17:49 +08007685 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 +08007686 fp = popen(pipeCmd, "r");
7687 if (fp)
7688 {
7689 pclose(fp);
7690 }
7691
7692 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7693 if (fp)
7694 {
7695 for (count = 0; count < wifi_count; count++)
7696 {
7697 fgets(str, MAX_BUF_SIZE, fp);
7698 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7699 }
7700 pclose(fp);
7701 }
7702
7703 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007704 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 +08007705 fp = popen(pipeCmd, "r");
7706 if (fp)
7707 {
7708 pclose(fp);
7709 }
7710 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7711 if (fp)
7712 {
7713 for (count = 0; count < wifi_count; count++)
7714 {
7715 fgets(str, MAX_BUF_SIZE, fp);
7716 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7717 }
7718 pclose(fp);
7719 }
7720
7721 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007722 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 +08007723 fp = popen(pipeCmd, "r");
7724 if (fp)
7725 {
7726 pclose(fp);
7727 }
7728 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7729 if (fp)
7730 {
7731 for (count = 0; count < wifi_count; count++)
7732 {
7733 fgets(str, MAX_BUF_SIZE, fp);
7734 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7735 }
7736 pclose(fp);
7737 }
7738
7739 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007740 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 +08007741 fp = popen(pipeCmd, "r");
7742 if (fp)
7743 {
7744 pclose(fp);
7745 }
7746 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7747 if (fp)
7748 {
7749 for (count = 0; count < wifi_count; count++)
7750 {
7751 fgets(str, MAX_BUF_SIZE, fp);
7752 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7753 }
7754 pclose(fp);
7755 }
7756
7757 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007758 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 +08007759 fp = popen(pipeCmd, "r");
7760 if (fp)
7761 {
7762 pclose(fp);
7763 }
7764 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7765 if (fp)
7766 {
7767 for (count = 0; count < wifi_count; count++)
7768 {
7769 fgets(str, MAX_BUF_SIZE, fp);
7770 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7771 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7772 }
7773 pclose(fp);
7774 }
7775
7776 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007777 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 +08007778 fp = popen(pipeCmd, "r");
7779 if (fp)
7780 {
7781 pclose(fp);
7782 }
7783 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7784 if (fp)
7785 {
7786 for (count = 0; count < wifi_count; count++)
7787 {
7788 fgets(str, MAX_BUF_SIZE, fp);
7789 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7790 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7791 }
7792 pclose(fp);
7793 }
7794
7795 }
7796 else if ((apIndex == 1) || (apIndex == 5))
7797 {
7798 for (count = 0; count < wifi_count; count++)
7799 {
7800 strcpy(temp[count].cli_OperatingStandard, "a");
7801 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7802 temp[count].cli_BytesSent = 0;
7803 temp[count].cli_BytesReceived = 0;
7804 temp[count].cli_LastDataUplinkRate = 0;
7805 temp[count].cli_LastDataDownlinkRate = 0;
7806 temp[count].cli_PacketsSent = 0;
7807 temp[count].cli_PacketsReceived = 0;
7808 temp[count].cli_ErrorsSent = 0;
7809 }
7810 }
7811
7812 for (count = 0; count < wifi_count; count++)
7813 {
7814 temp[count].cli_Retransmissions = 0;
7815 temp[count].cli_DataFramesSentAck = 0;
7816 temp[count].cli_DataFramesSentNoAck = 0;
7817 temp[count].cli_MinRSSI = 0;
7818 temp[count].cli_MaxRSSI = 0;
7819 strncpy(temp[count].cli_InterferenceSources, "", 64);
7820 memset(temp[count].cli_IPAddress, 0, 64);
7821 temp[count].cli_RetransCount = 0;
7822 temp[count].cli_FailedRetransCount = 0;
7823 temp[count].cli_RetryCount = 0;
7824 temp[count].cli_MultipleRetryCount = 0;
7825 }
7826 *associated_dev_array = temp;
7827 }
7828 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7829 return RETURN_OK;
7830}
7831
7832int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7833{
7834 FILE *fp = NULL;
7835 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7836 char cmd[MAX_CMD_SIZE];
7837 int count = 0;
7838
7839 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7840 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7841 fp = popen(cmd,"r");
7842 if(fp == NULL)
7843 {
7844 printf("Failed to run command in Function %s\n",__FUNCTION__);
7845 return 0;
7846 }
7847 if(fgets(path, sizeof(path)-1, fp) != NULL)
7848 {
7849 for(count=0;path[count]!='\n';count++)
7850 status[count]=path[count];
7851 status[count]='\0';
7852 }
7853 strcpy(wifi_status,status);
7854 pclose(fp);
7855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7856 return RETURN_OK;
7857}
7858
7859/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7860struct hostapd_sta_param {
7861 char key[50];
7862 char value[100];
7863}
7864
7865static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7866 int i = 0;
7867
7868 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7869 if (strncmp(params[i].key,key,50) == 0){
7870 return &params[i].value;
7871 }
7872 i++;
7873 }
7874 return NULL;
7875
7876} */
7877
7878static unsigned int count_occurences(const char *buf, const char *word)
7879{
7880 unsigned int n = 0;
7881 char *ptr = strstr(buf, word);
7882
7883 while (ptr++) {
7884 n++;
7885 ptr = strstr(ptr, word);
7886 }
7887
7888 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7889 return n;
7890}
7891
7892static const char *get_line_from_str_buf(const char *buf, char *line)
7893{
7894 int i;
7895 int n = strlen(buf);
7896
7897 for (i = 0; i < n; i++) {
7898 line[i] = buf[i];
7899 if (buf[i] == '\n') {
7900 line[i] = '\0';
7901 return &buf[i + 1];
7902 }
7903 }
7904
7905 return NULL;
7906}
7907
developer9a9f46e2023-11-09 09:22:42 +08007908static INT wifi_getAssocConnectMode(INT apIndex, CHAR *input_string, CHAR *OperatingStandard)
7909{
7910 wifi_band band;
7911 int ieee80211_mode = 0;
7912
7913 if (!input_string || !OperatingStandard)
7914 return RETURN_ERR;
7915
7916 band = wifi_index_to_band(apIndex);
7917
7918 if (strstr(input_string, "HE"))
7919 ieee80211_mode = WIFI_MODE_AX;
7920 else if (strstr(input_string, "VHT"))
7921 ieee80211_mode = WIFI_MODE_AC;
7922 else if (strstr(input_string, "EHT"))
7923 ieee80211_mode = WIFI_MODE_BE;
7924
7925 switch (ieee80211_mode) {
7926 case WIFI_MODE_AC:
7927 strncpy(OperatingStandard, "ac", 2);
7928 break;
7929 case WIFI_MODE_AX:
7930 strncpy(OperatingStandard, "ax", 2);
7931 break;
7932 case WIFI_MODE_BE:
7933 strncpy(OperatingStandard, "be", 2);
7934 break;
7935 default:
7936 if(band == band_2_4)
7937 strncpy(OperatingStandard,"b,g,n", 5);
7938 else if(band == band_5)
7939 strncpy(OperatingStandard,"a,n", 3);
7940 else if(band == band_6)
7941 strncpy(OperatingStandard,"ax", 2);
7942 else {
7943 wifi_dbg_printf("%s: failed to parse band %d\n", __FUNCTION__, band);
7944 return RETURN_ERR;
7945 }
7946 }
7947
7948
7949 return RETURN_OK;
7950}
7951
developer06a01d92022-09-07 16:32:39 +08007952INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7953{
7954 unsigned int assoc_cnt = 0;
7955 char interface_name[50] = {0};
7956 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7957 char cmd[MAX_CMD_SIZE] = {'\0'};
7958 char line[256] = {'\0'};
7959 int i = 0;
7960 int ret = 0;
7961 const char *ptr = NULL;
7962 char *key = NULL;
7963 char *val = NULL;
7964 wifi_associated_dev3_t *temp = NULL;
7965 int rssi;
7966
7967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7968
7969 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7970 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7971 return RETURN_ERR;
7972 }
7973
7974 // Example filtered output of 'iw dev' command:
7975 // Station 0a:69:72:10:d2:fa (on wifi0)
7976 // signal avg:-67 [-71, -71] dBm
7977 // Station 28:c2:1f:25:5f:99 (on wifi0)
7978 // signal avg:-67 [-71, -70] dBm
developer9a9f46e2023-11-09 09:22:42 +08007979 if (sprintf(cmd,"iw dev %s station dump | tr -d '\t' | grep -E 'Station|signal avg"
7980 "|tx bitrate|rx bitrate'", interface_name) < 0) {
7981 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
developer06a01d92022-09-07 16:32:39 +08007982 return RETURN_ERR;
7983 }
7984
7985 ret = _syscmd(cmd, buf, sizeof(buf));
7986 if (ret == RETURN_ERR) {
7987 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7988 return RETURN_ERR;
7989 }
7990
7991 *output_array_size = count_occurences(buf, "Station");
7992 if (*output_array_size == 0) return RETURN_OK;
7993
7994 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7995 if (temp == NULL) {
7996 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7997 return RETURN_ERR;
7998 }
7999 *associated_dev_array = temp;
8000
8001 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
8002 ptr = get_line_from_str_buf(buf, line);
8003 i = -1;
8004 while (ptr) {
8005 if (strstr(line, "Station")) {
8006 i++;
8007 key = strtok(line, " ");
8008 val = strtok(NULL, " ");
8009 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8010 &temp[i].cli_MACAddress[0],
8011 &temp[i].cli_MACAddress[1],
8012 &temp[i].cli_MACAddress[2],
8013 &temp[i].cli_MACAddress[3],
8014 &temp[i].cli_MACAddress[4],
8015 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8016 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8017 free(*associated_dev_array);
8018 return RETURN_ERR;
8019 }
8020 }
8021 else if (i < 0) {
developer9a9f46e2023-11-09 09:22:42 +08008022 wifi_dbg_printf("%s: not find station\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +08008023 ptr = get_line_from_str_buf(ptr, line);
8024 continue; // We didn't detect 'station' entry yet
8025 }
8026 else if (strstr(line, "signal avg")) {
8027 key = strtok(line, ":");
8028 val = strtok(NULL, " ");
8029 if (sscanf(val, "%d", &rssi) <= 0 ) {
8030 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8031 free(*associated_dev_array);
8032 return RETURN_ERR;
8033 }
8034 temp[i].cli_RSSI = rssi;
8035 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8036 }
developer9a9f46e2023-11-09 09:22:42 +08008037 else if (strstr(line, "tx bitrate")) {
8038 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8039 if (ret == RETURN_ERR) {
8040 wifi_dbg_printf("%s: failed to execute tx get assoc connect mode command.\n", __FUNCTION__);
8041 return ret;
8042 }
8043 }
8044 else if (strstr(line, "rx bitrate")) {
8045 /* if tx get ac, ax, be mode, need not get mode from rx */
8046 if (strncmp(temp[i].cli_OperatingStandard,"ac", 2) &&
8047 strncmp(temp[i].cli_OperatingStandard,"ax", 2) &&
8048 strncmp(temp[i].cli_OperatingStandard,"be", 2)) {
8049 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8050 if (ret == RETURN_ERR) {
8051 wifi_dbg_printf("%s: failed to execute rx get assoc connect mode command.\n", __FUNCTION__);
8052 return ret;
8053 }
8054 }
8055 }
developer06a01d92022-09-07 16:32:39 +08008056 // Here other fields can be parsed if added to filter of 'iw dev' command
developer06a01d92022-09-07 16:32:39 +08008057 ptr = get_line_from_str_buf(ptr, line);
developer9a9f46e2023-11-09 09:22:42 +08008058 }
developer06a01d92022-09-07 16:32:39 +08008059
8060 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008061 return RETURN_OK;
8062}
8063
8064#if 0
8065//To-do
8066INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8067{
8068 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8069
8070 //Using different approach to get required WiFi Parameters from system available commands
8071#if 0
8072 FILE *f;
8073 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8074 char cmd[256], buf[2048];
8075 char *param , *value, *line=NULL;
8076 size_t len = 0;
8077 ssize_t nread;
8078 wifi_associated_dev3_t *dev=NULL;
8079 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08008080 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08008081 _syscmd(cmd,buf,sizeof(buf));
8082 *output_array_size = atoi(buf);
8083
8084 if (*output_array_size <= 0)
8085 return RETURN_OK;
8086
8087 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8088 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08008089 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08008090 _syscmd(cmd,buf,sizeof(buf));
8091 f = fopen("/tmp/connected_devices.txt", "r");
8092 if (f==NULL)
8093 {
8094 *output_array_size=0;
8095 return RETURN_ERR;
8096 }
8097 while ((nread = getline(&line, &len, f)) != -1)
8098 {
8099 param = strtok(line,"=");
8100 value = strtok(NULL,"=");
8101
8102 if( strcmp("flags",param) == 0 )
8103 {
8104 value[strlen(value)-1]='\0';
8105 if(strstr (value,"AUTHORIZED") != NULL )
8106 {
8107 dev[auth_temp].cli_AuthenticationState = 1;
8108 dev[auth_temp].cli_Active = 1;
8109 auth_temp++;
8110 read_flag=1;
8111 }
8112 }
8113 if(read_flag==1)
8114 {
8115 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8116 {
8117 value[strlen(value)-1]='\0';
8118 sscanf(value, "%x:%x:%x:%x:%x:%x",
8119 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8120 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8121 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8122 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8123 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8124 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8125
8126 }
8127 else if( strcmp("rx_packets",param) == 0 )
8128 {
8129 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8130 }
8131
8132 else if( strcmp("tx_packets",param) == 0 )
8133 {
8134 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8135 }
8136
8137 else if( strcmp("rx_bytes",param) == 0 )
8138 {
8139 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8140 }
8141
8142 else if( strcmp("tx_bytes",param) == 0 )
8143 {
8144 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8145 mac_temp++;
8146 read_flag=0;
8147 }
8148 }
8149 }
8150
8151 *output_array_size = auth_temp;
8152 auth_temp=0;
8153 mac_temp=0;
8154 free(line);
8155 fclose(f);
8156#endif
8157 char interface_name[MAX_BUF_SIZE] = {0};
8158 char wifi_status[MAX_BUF_SIZE] = {0};
8159 char hostapdconf[MAX_BUF_SIZE] = {0};
8160
8161 wifi_associated_dev3_t *dev_array = NULL;
8162 ULONG wifi_count = 0;
8163
8164 *associated_dev_array = NULL;
8165 *output_array_size = 0;
8166
8167 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8168 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8169 {
8170 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8171
developerac6f1142022-12-20 19:26:35 +08008172 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008173
8174 if(strlen(interface_name) > 1)
8175 {
8176 wifihal_interfacestatus(wifi_status,interface_name);
8177 if(strcmp(wifi_status,"RUNNING") == 0)
8178 {
8179 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8180
8181 *associated_dev_array = dev_array;
8182 *output_array_size = wifi_count;
8183 }
8184 else
8185 {
8186 *associated_dev_array = NULL;
8187 }
8188 }
8189 }
8190
8191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8192 return RETURN_OK;
8193}
8194#endif
8195
8196/* getIPAddress function */
8197/**
8198* @description Returning IpAddress of the Matched String
8199*
8200* @param
8201* @str Having MacAddress
8202* @ipaddr Having ipaddr
8203* @return The status of the operation
8204* @retval RETURN_OK if successful
8205* @retval RETURN_ERR if any error is detected
8206*
8207*/
8208
8209INT getIPAddress(char *str,char *ipaddr)
8210{
8211 FILE *fp = NULL;
8212 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8213 int LeaseTime = 0,ret = 0;
8214 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8215 {
8216 return RETURN_ERR;
8217 }
8218
8219 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8220 {
8221 /*
8222 Sample:sss
8223 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8224 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8225 */
8226 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008227 &(LeaseTime),
8228 phyAddr,
8229 ipAddr,
8230 hostName
8231 );
developer06a01d92022-09-07 16:32:39 +08008232 if(ret != 4)
8233 continue;
8234 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008235 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008236 }
developerd946fd62022-12-08 18:03:28 +08008237 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008238 return RETURN_OK;
8239}
8240
8241/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8242/**
8243* @description Returning Inactive wireless connected clients informations
8244*
8245* @param
8246* @filename Holding private_wifi 2g/5g content files
8247* @associated_dev_array Having inactiv wireless clients informations
8248* @output_array_size Returning Inactive wireless counts
8249* @return The status of the operation
8250* @retval RETURN_OK if successful
8251* @retval RETURN_ERR if any error is detected
8252*
8253*/
8254
8255INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8256{
8257 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8258 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8259 FILE *fp = NULL;
8260 int arr[MACADDRESS_SIZE] = {0};
8261 unsigned char mac[MACADDRESS_SIZE] = {0};
8262 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8263 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8264 fp = popen(buf,"r");
8265 if(fp == NULL)
8266 return RETURN_ERR;
8267 else
8268 {
8269 fgets(path,sizeof(path),fp);
8270 maccount = atoi(path);
8271 }
8272 pclose(fp);
8273 *output_array_size = maccount;
8274 wifi_associated_dev3_t* temp = NULL;
8275 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8276 *associated_dev_array = temp;
8277 if(temp == NULL)
8278 {
8279 printf("Error Statement. Insufficient memory \n");
8280 return RETURN_ERR;
8281 }
8282 memset(buf,0,sizeof(buf));
8283 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8284 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008285 if (fp == NULL) {
8286 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8287 return RETURN_ERR;
8288 }
developer06a01d92022-09-07 16:32:39 +08008289 for(count = 0; count < maccount ; count++)
8290 {
8291 fgets(path,sizeof(path),fp);
8292 for(i = 0; path[i]!='\n';i++)
8293 str[i]=path[i];
8294 str[i]='\0';
8295 getIPAddress(str,ipaddr);
8296 memset(buf,0,sizeof(buf));
8297 if(strlen(ipaddr) > 0)
8298 {
8299 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8300 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8301 {
8302 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8303 {
8304 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8305 {
8306 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8307
8308 }
8309 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8310 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]);
8311 }
8312 temp[count].cli_AuthenticationState = 0; //TODO
8313 temp[count].cli_Active = 0; //TODO
8314 temp[count].cli_SignalStrength = 0;
8315 }
8316 else //Active wireless clients info
8317 {
8318 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8319 {
8320 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8321 {
8322 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8323
8324 }
8325 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8326 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]);
8327 }
8328 temp[count].cli_Active = 1;
8329 }
8330 }
8331 memset(ipaddr,0,sizeof(ipaddr));
8332 }
8333 pclose(fp);
8334 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8335 return RETURN_OK;
8336}
8337//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8338//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8339//To get Band Steering Capability
8340INT wifi_getBandSteeringCapability(BOOL *support)
8341{
8342 *support = FALSE;
8343 return RETURN_OK;
8344}
8345
8346
8347//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8348//To get Band Steering enable status
8349INT wifi_getBandSteeringEnable(BOOL *enable)
8350{
8351 *enable = FALSE;
8352 return RETURN_OK;
8353}
8354
8355//To turn on/off Band steering
8356INT wifi_setBandSteeringEnable(BOOL enable)
8357{
8358 return RETURN_OK;
8359}
8360
8361//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8362//To get Band Steering AP group
8363INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8364{
8365 if (NULL == output_ApGroup)
8366 return RETURN_ERR;
8367
8368 strcpy(output_ApGroup, "1,2");
8369 return RETURN_OK;
8370}
8371
8372//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8373//to set and read the band steering BandUtilizationThreshold parameters
8374INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8375{
8376 return RETURN_ERR;
8377}
8378
8379INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8380{
8381 return RETURN_ERR;
8382}
8383
8384//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8385//to set and read the band steering RSSIThreshold parameters
8386INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8387{
8388 return RETURN_ERR;
8389}
8390
8391INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8392{
8393 return RETURN_ERR;
8394}
8395
8396
8397//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8398//to set and read the band steering physical modulation rate threshold parameters
8399INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8400{
8401 //If chip is not support, return -1
8402 return RETURN_ERR;
8403}
8404
8405INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8406{
8407 //If chip is not support, return -1
8408 return RETURN_ERR;
8409}
8410
8411//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8412//to set and read the inactivity time (in seconds) for steering under overload condition
8413INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8414{
8415 return RETURN_ERR;
8416}
8417
8418INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8419{
8420 return RETURN_ERR;
8421}
8422
8423//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8424//to set and read the inactivity time (in seconds) for steering under Idle condition
8425INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8426{
8427 return RETURN_ERR;
8428}
8429
8430INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8431{
8432 return RETURN_ERR;
8433}
8434
8435//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8436//pClientMAC[64]
8437//pSourceSSIDIndex[64]
8438//pDestSSIDIndex[64]
8439//pSteeringReason[256]
8440INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8441{
8442 //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
8443 *pSteeringTime=time(NULL);
8444 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8445 return RETURN_OK;
8446}
8447
8448INT wifi_ifConfigDown(INT apIndex)
8449{
8450 INT status = RETURN_OK;
8451 char cmd[64];
8452
8453 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8454 printf("%s: %s\n", __func__, cmd);
8455 system(cmd);
8456
8457 return status;
8458}
8459
8460INT wifi_ifConfigUp(INT apIndex)
8461{
developerd946fd62022-12-08 18:03:28 +08008462 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008463 char cmd[128];
8464 char buf[1024];
8465
developerac6f1142022-12-20 19:26:35 +08008466 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008467 return RETURN_ERR;
8468 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008469 _syscmd(cmd, buf, sizeof(buf));
8470 return 0;
8471}
8472
8473//>> Deprecated. Replace with wifi_applyRadioSettings
8474INT wifi_pushBridgeInfo(INT apIndex)
8475{
developerd946fd62022-12-08 18:03:28 +08008476 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008477 char ip[32] = {0};
8478 char subnet[32] = {0};
8479 char bridge[32] = {0};
8480 int vlanId = 0;
8481 char cmd[128] = {0};
8482 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008483
8484 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8485 wifi_getApVlanID(apIndex,&vlanId);
8486
developerac6f1142022-12-20 19:26:35 +08008487 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008488 return RETURN_ERR;
8489 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008490 _syscmd(cmd,buf, sizeof(buf));
8491
8492 return 0;
8493}
8494
8495INT wifi_pushChannel(INT radioIndex, UINT channel)
8496{
developerd946fd62022-12-08 18:03:28 +08008497 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008498 char cmd[128];
8499 char buf[1024];
8500 int apIndex;
8501
8502 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008503 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008504 return RETURN_ERR;
8505 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008506 _syscmd(cmd,buf, sizeof(buf));
8507
8508 return 0;
8509}
8510
8511INT wifi_pushChannelMode(INT radioIndex)
8512{
8513 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8514 return RETURN_ERR;
8515}
8516
8517INT wifi_pushDefaultValues(INT radioIndex)
8518{
8519 //Apply Comcast specified default radio settings instantly
8520 //AMPDU=1
8521 //AMPDUFrames=32
8522 //AMPDULim=50000
8523 //txqueuelen=1000
8524
8525 return RETURN_ERR;
8526}
8527
8528INT wifi_pushTxChainMask(INT radioIndex)
8529{
8530 //Apply default TxChainMask instantly
8531 return RETURN_ERR;
8532}
8533
8534INT wifi_pushRxChainMask(INT radioIndex)
8535{
8536 //Apply default RxChainMask instantly
8537 return RETURN_ERR;
8538}
8539
8540INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8541{
8542 INT status;
8543
8544 status = wifi_setSSIDName(apIndex,ssid);
8545 wifi_setApEnable(apIndex,FALSE);
8546 wifi_setApEnable(apIndex,TRUE);
8547
8548 return status;
8549}
8550
8551INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8552{
8553 //Apply default Ssid Advertisement instantly
8554 return RETURN_ERR;
8555}
8556
8557INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8558{
8559 INT status = RETURN_ERR;
8560 *output = 0;
8561 return RETURN_ERR;
8562}
8563
8564INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8565{
8566 return RETURN_OK;
8567}
8568
8569INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8570{
8571 return RETURN_OK;
8572}
8573
8574//To-do
8575INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8576{
developereb199ae2022-09-13 14:04:27 +08008577 char output[16]={'\0'};
8578 char config_file[MAX_BUF_SIZE] = {0};
8579
8580 if (!output_string)
8581 return RETURN_ERR;
8582
8583 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8584 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8585
8586 if (strlen(output) == 0)
8587 snprintf(output_string, 64, "Disabled");
8588 else if (strncmp(output, "0", 1) == 0)
8589 snprintf(output_string, 64, "Disabled");
8590 else if (strncmp(output, "1", 1) == 0)
8591 snprintf(output_string, 64, "Optional");
8592 else if (strncmp(output, "2", 1) == 0)
8593 snprintf(output_string, 64, "Required");
8594 else {
8595 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8596 return RETURN_ERR;
8597 }
8598
8599 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008600 return RETURN_OK;
8601}
8602INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8603{
developereb199ae2022-09-13 14:04:27 +08008604 char str[MAX_BUF_SIZE]={'\0'};
8605 char cmd[MAX_CMD_SIZE]={'\0'};
8606 struct params params;
8607 char config_file[MAX_BUF_SIZE] = {0};
8608
8609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8610 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8611 return RETURN_ERR;
8612
8613 params.name = "ieee80211w";
8614 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8615 params.value = "0";
8616 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8617 params.value = "1";
8618 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8619 params.value = "2";
8620 else{
8621 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8622 return RETURN_ERR;
8623 }
8624 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8625 wifi_hostapdWrite(config_file, &params, 1);
8626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008627 return RETURN_OK;
8628}
8629INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8630{
8631 char output[16]={'\0'};
8632 char config_file[MAX_BUF_SIZE] = {0};
8633
8634 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8635 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8636 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8637
8638 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8639 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8640
8641 return RETURN_OK;
8642}
8643
8644INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8645{
8646 return RETURN_OK;
8647}
8648
8649INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8650{
8651 return RETURN_OK;
8652}
8653
8654INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8655{
8656 return RETURN_OK;
8657}
8658
8659INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8660{
8661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8662 char config_file[MAX_BUF_SIZE] = {0};
8663
8664 if (NULL == output)
8665 return RETURN_ERR;
8666 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8667 wifi_hostapdRead(config_file,"hw_mode",output,64);
8668
8669 if(strcmp(output,"b")==0)
8670 sprintf(output, "%s", "1,2,5.5,11");
8671 else if (strcmp(output,"a")==0)
8672 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8673 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8674 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8675
8676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8677 return RETURN_OK;
8678}
8679
8680INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8681{
8682 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8683 char *temp;
8684 char temp_output[128];
8685 char temp_TransmitRates[128];
8686 char config_file[MAX_BUF_SIZE] = {0};
8687
8688 if (NULL == output)
8689 return RETURN_ERR;
8690
8691 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8692 wifi_hostapdRead(config_file,"supported_rates",output,64);
8693
developer5b398df2022-11-17 20:39:48 +08008694 if (strlen(output) == 0) {
8695 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8696 return RETURN_OK;
8697 }
developer06a01d92022-09-07 16:32:39 +08008698 strcpy(temp_TransmitRates,output);
8699 strcpy(temp_output,"");
8700 temp = strtok(temp_TransmitRates," ");
8701 while(temp!=NULL)
8702 {
8703 temp[strlen(temp)-1]=0;
8704 if((temp[0]=='5') && (temp[1]=='\0'))
8705 {
8706 temp="5.5";
8707 }
8708 strcat(temp_output,temp);
8709 temp = strtok(NULL," ");
8710 if(temp!=NULL)
8711 {
8712 strcat(temp_output,",");
8713 }
8714 }
8715 strcpy(output,temp_output);
8716 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8717
8718 return RETURN_OK;
8719}
8720
8721INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8722{
8723 return RETURN_OK;
8724}
8725
8726
8727INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8728{
8729 int i=0;
8730 char *temp;
developeref938762022-10-19 17:21:01 +08008731 char temp1[128] = {0};
8732 char temp_output[128] = {0};
8733 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008734 struct params params={'\0'};
8735 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008736 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008737
8738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8739 if(NULL == output)
8740 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008741 strcpy(temp_TransmitRates,output);
8742
8743 for(i=0;i<strlen(temp_TransmitRates);i++)
8744 {
developeref938762022-10-19 17:21:01 +08008745 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008746 {
8747 continue;
8748 }
8749 else
8750 {
8751 return RETURN_ERR;
8752 }
8753 }
8754 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008755 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008756 while(temp!=NULL)
8757 {
8758 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008759 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008760 {
developeref938762022-10-19 17:21:01 +08008761 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008762 {
8763 return RETURN_ERR;
8764 }
8765 }
8766
8767 if(strcmp(temp,"5.5")==0)
8768 {
8769 strcpy(temp1,"55");
8770 }
8771 else
8772 {
8773 strcat(temp1,"0");
8774 }
8775 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008776 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008777 if(temp!=NULL)
8778 {
8779 strcat(temp_output," ");
8780 }
8781 }
8782 strcpy(output,temp_output);
8783
developer06a01d92022-09-07 16:32:39 +08008784 params.name = "supported_rates";
8785 params.value = output;
8786
8787 wifi_dbg_printf("\n%s:",__func__);
8788 wifi_dbg_printf("params.value=%s\n",params.value);
8789 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8790 wifi_hostapdWrite(config_file,&params,1);
8791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8792
8793 return RETURN_OK;
8794}
8795
8796
8797static char *sncopy(char *dst, int dst_sz, const char *src)
8798{
8799 if (src && dst && dst_sz > 0) {
8800 strncpy(dst, src, dst_sz);
8801 dst[dst_sz - 1] = '\0';
8802 }
8803 return dst;
8804}
8805
8806static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8807{
8808 if (0 == strcmp(ht_mode, "HT40") ||
8809 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008810 0 == strcmp(ht_mode, "HT160") ||
8811 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008812 switch (channel) {
developer9a520b12023-09-21 16:01:43 +08008813 case 0 ... 7:
developer06a01d92022-09-07 16:32:39 +08008814 case 36:
8815 case 44:
8816 case 52:
8817 case 60:
8818 case 100:
8819 case 108:
8820 case 116:
8821 case 124:
8822 case 132:
8823 case 140:
8824 case 149:
8825 case 157:
8826 return 1;
8827 case 8 ... 13:
8828 case 40:
8829 case 48:
8830 case 56:
8831 case 64:
8832 case 104:
8833 case 112:
8834 case 120:
8835 case 128:
8836 case 136:
8837 case 144:
8838 case 153:
8839 case 161:
8840 return -1;
8841 default:
8842 return -EINVAL;
8843 }
8844 }
8845
8846 return -EINVAL;
8847}
8848
developerb7593de2022-10-18 09:51:57 +08008849static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8850{
8851 int idx = channel%8;
8852 if (0 == strcmp(ht_mode, "HT40") ||
8853 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008854 0 == strcmp(ht_mode, "HT160") ||
8855 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008856 switch (idx) {
8857 case 1:
8858 return 1;
8859 case 5:
8860 return -1;
8861 default:
8862 return -EINVAL;
8863 }
8864 }
8865
8866 return -EINVAL;
8867}
developer06a01d92022-09-07 16:32:39 +08008868static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8869{
8870 if (NULL == hw_mode) return;
8871
8872 if (0 == strcmp(hw_mode, "ac"))
8873 sncopy(bw_mode, bw_mode_len, "ht vht");
8874
8875 if (0 == strcmp(hw_mode, "n"))
8876 sncopy(bw_mode, bw_mode_len, "ht");
8877
8878 return;
8879}
8880
8881static int util_chan_to_freq(int chan)
8882{
8883 if (chan == 14)
8884 return 2484;
8885 else if (chan < 14)
8886 return 2407 + chan * 5;
8887 else if (chan >= 182 && chan <= 196)
8888 return 4000 + chan * 5;
8889 else
8890 return 5000 + chan * 5;
8891 return 0;
8892}
8893
developerb7593de2022-10-18 09:51:57 +08008894static int util_6G_chan_to_freq(int chan)
8895{
8896 if (chan)
8897 return 5950 + chan * 5;
8898 else
8899 return 0;
8900
8901}
developer06a01d92022-09-07 16:32:39 +08008902const int *util_unii_5g_chan2list(int chan, int width)
8903{
8904 static const int lists[] = {
8905 // <width>, <chan1>, <chan2>..., 0,
developer8b2f01f2024-03-01 14:50:27 +08008906 20, 36, 0,
8907 20, 40, 0,
8908 20, 44, 0,
8909 20, 48, 0,
8910 20, 52, 0,
8911 20, 56, 0,
8912 20, 60, 0,
8913 20, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008914 20, 100, 0,
8915 20, 104, 0,
8916 20, 108, 0,
8917 20, 112, 0,
8918 20, 116, 0,
8919 20, 120, 0,
8920 20, 124, 0,
8921 20, 128, 0,
8922 20, 132, 0,
8923 20, 136, 0,
8924 20, 140, 0,
8925 20, 144, 0,
8926 20, 149, 0,
8927 20, 153, 0,
8928 20, 157, 0,
8929 20, 161, 0,
8930 20, 165, 0,
developer8b2f01f2024-03-01 14:50:27 +08008931 20, 169, 0,
8932 20, 173, 0,
8933 20, 177, 0,
8934 40, 36, 40, 0,
8935 40, 44, 48, 0,
8936 40, 52, 56, 0,
8937 40, 60, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008938 40, 100, 104, 0,
8939 40, 108, 112, 0,
8940 40, 116, 120, 0,
8941 40, 124, 128, 0,
8942 40, 132, 136, 0,
8943 40, 140, 144, 0,
8944 40, 149, 153, 0,
8945 40, 157, 161, 0,
developer8b2f01f2024-03-01 14:50:27 +08008946 40, 165, 169, 0,
8947 40, 173, 177, 0,
8948 80, 36, 40, 44, 48, 0,
8949 80, 52, 56, 60, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008950 80, 100, 104, 108, 112, 0,
8951 80, 116, 120, 124, 128, 0,
8952 80, 132, 136, 140, 144, 0,
8953 80, 149, 153, 157, 161, 0,
developer8b2f01f2024-03-01 14:50:27 +08008954 80, 165, 169, 173, 177, 0,
8955 160,36, 40, 44, 48, 52, 56, 60, 64, 0,
8956 160,100, 104, 108, 112, 116, 120, 124, 128, 0,
8957 160,149, 153, 157, 161, 165, 169, 173, 177, 0,
developer06a01d92022-09-07 16:32:39 +08008958 -1 // final delimiter
8959 };
8960 const int *start;
8961 const int *p;
8962
8963 for (p = lists; *p != -1; p++) {
8964 if (*p == width) {
8965 for (start = ++p; *p != 0; p++) {
8966 if (*p == chan)
8967 return start;
8968 }
8969 }
8970 // move to the end of channel list of given width
8971 while (*p != 0) {
8972 p++;
8973 }
8974 }
8975
8976 return NULL;
8977}
8978
8979static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8980{
8981 if (NULL == ht_mode)
8982 return 0;
8983
8984 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8985 const int *chans = util_unii_5g_chan2list(channel, width);
8986 int sum = 0;
8987 int cnt = 0;
8988
8989 if (NULL == chans)
8990 return 0;
8991
8992 while (*chans) {
8993 sum += *chans;
8994 cnt++;
8995 chans++;
8996 }
developer30423732022-12-01 16:17:49 +08008997 if (cnt == 0)
8998 return 0;
developer06a01d92022-09-07 16:32:39 +08008999 return sum / cnt;
9000}
9001
developerb7593de2022-10-18 09:51:57 +08009002static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
9003{
9004 if (NULL == ht_mode)
9005 return 0;
9006
9007 int width = strtol((ht_mode + 2), NULL, 10);
9008
9009 int idx = 0 ;
9010 int centerchan = 0;
9011 int chan_ofs = 1;
9012
9013 if (width == 40){
9014 idx = ((channel/4) + chan_ofs)%2;
9015 switch (idx) {
9016 case 0:
9017 centerchan = (channel - 2);
9018 break;
9019 case 1:
9020 centerchan = (channel + 2);
9021 break;
9022 default:
9023 return -EINVAL;
9024 }
9025 }else if (width == 80){
9026 idx = ((channel/4) + chan_ofs)%4;
9027 switch (idx) {
9028 case 0:
9029 centerchan = (channel - 6);
9030 break;
9031 case 1:
9032 centerchan = (channel + 6);
9033 break;
9034 case 2:
9035 centerchan = (channel + 2);
9036 break;
9037 case 3:
9038 centerchan = (channel - 2);
9039 break;
9040 default:
9041 return -EINVAL;
9042 }
9043 }else if (width == 160){
9044 switch (channel) {
9045 case 1 ... 29:
9046 centerchan = 15;
9047 break;
9048 case 33 ... 61:
9049 centerchan = 47;
9050 break;
9051 case 65 ... 93:
9052 centerchan = 79;
9053 break;
9054 case 97 ... 125:
9055 centerchan = 111;
9056 break;
9057 case 129 ... 157:
9058 centerchan = 143;
9059 break;
9060 case 161 ... 189:
9061 centerchan = 175;
9062 break;
9063 case 193 ... 221:
9064 centerchan = 207;
9065 break;
9066 default:
9067 return -EINVAL;
9068 }
developer7c4cd202023-03-01 10:56:29 +08009069 }else if (width == 320){
9070 switch (channel) {
9071 case 1 ... 29:
9072 centerchan = 31;
9073 break;
9074 case 33 ... 93:
9075 centerchan = 63;
9076 break;
9077 case 97 ... 157:
9078 centerchan = 127;
9079 break;
9080 case 161 ... 221:
9081 centerchan = 191;
9082 break;
9083 default:
9084 return -EINVAL;
9085 }
developerb7593de2022-10-18 09:51:57 +08009086 }
9087 return centerchan;
9088}
developer06a01d92022-09-07 16:32:39 +08009089static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9090{
9091 BOOL onlyG, onlyN, onlyA;
9092 CHAR tmp[64];
9093 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9094 if (ret == RETURN_OK) {
9095 sncopy(hw_mode, hw_mode_size, tmp);
9096 }
9097 return ret;
9098}
9099
9100INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9101{
9102 // Sample commands:
9103 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9104 // hostapd_cli -i wifi0 chan_switch 30 2437
9105 char cmd[MAX_CMD_SIZE] = {0};
9106 char buf[MAX_BUF_SIZE] = {0};
9107 int freq = 0, ret = 0;
9108 char center_freq1_str[32] = ""; // center_freq1=%d
9109 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9110 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9111 char hw_mode[16] = ""; // n|ac
9112 char bw_mode[16] = ""; // ht|ht vht
9113 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08009114 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009115 int sec_chan_offset;
9116 int width;
developer4fb0b922022-09-30 14:29:09 +08009117 char config_file[64] = {0};
9118 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08009119 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08009120 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08009121 wifi_band band = band_invalid;
9122 int center_chan = 0;
9123 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08009124
developer4fb0b922022-09-30 14:29:09 +08009125 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08009126
developerac6f1142022-12-20 19:26:35 +08009127 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009128 return RETURN_ERR;
9129
developer06a01d92022-09-07 16:32:39 +08009130 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9131
developerb7593de2022-10-18 09:51:57 +08009132 band = wifi_index_to_band(radioIndex);
9133
developer5884e982022-10-06 10:52:50 +08009134 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08009135
9136 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08009137 if (channel){
developerb7593de2022-10-18 09:51:57 +08009138 if (band == band_6){
9139 freq = util_6G_chan_to_freq(channel);
9140 }else{
9141 freq = util_chan_to_freq(channel);
9142 }
developer7c4cd202023-03-01 10:56:29 +08009143 if (width == 320) {
9144 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
9145 setEHT320 = TRUE;
9146 }
developer5884e982022-10-06 10:52:50 +08009147 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08009148
developer5884e982022-10-06 10:52:50 +08009149 // Provide bandwith if specified
9150 if (channel_width_MHz > 20) {
9151 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9152 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9153 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08009154
developer5884e982022-10-06 10:52:50 +08009155 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9156 }else if (channel_width_MHz == 20){
9157 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9158 }
developer06a01d92022-09-07 16:32:39 +08009159
developerb7593de2022-10-18 09:51:57 +08009160
developer5884e982022-10-06 10:52:50 +08009161 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08009162 if (band == band_6){
9163 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9164 if(center_chan){
9165 center_freq1 = util_6G_chan_to_freq(center_chan);
9166 }
9167 }else{
9168 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9169 if(center_chan){
9170 center_freq1 = util_chan_to_freq(center_chan);
9171 }
developer5884e982022-10-06 10:52:50 +08009172 }
developerb7593de2022-10-18 09:51:57 +08009173
9174 if (center_freq1)
9175 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9176
9177 }
9178
9179 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9180 if (band == band_6){
9181 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9182 }else{
9183 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009184 }
developerb7593de2022-10-18 09:51:57 +08009185 if (sec_chan_offset != -EINVAL)
9186 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009187
developer5884e982022-10-06 10:52:50 +08009188 // Only the first AP, other are hanging on the same radio
9189 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009190 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9191 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009192 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9193 wifi_dbg_printf("execute: '%s'\n", cmd);
9194 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009195 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009196
developer5884e982022-10-06 10:52:50 +08009197 ret = wifi_setRadioChannel(radioIndex, channel);
9198 if (ret != RETURN_OK) {
9199 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9200 return RETURN_ERR;
9201 }
9202
9203 if (sec_chan_offset == 1) ext_str = "Above";
9204 else if (sec_chan_offset == -1) ext_str = "Below";
9205
9206 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009207
developer5884e982022-10-06 10:52:50 +08009208 } else {
9209 if (channel_width_MHz > 20)
9210 ext_str = "Above";
9211 }
developer4fb0b922022-09-30 14:29:09 +08009212
developer06a01d92022-09-07 16:32:39 +08009213 char mhz_str[16];
9214 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009215 if (setEHT320 == TRUE)
9216 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9217 else
9218 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009219
developer57fa24a2023-03-15 17:25:07 +08009220 writeBandWidth(radioIndex, mhz_str);
9221 if (band == band_2_4 || band == band_5) {
9222 if (width == 20)
9223 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9224 else
9225 wifi_setRadioExtChannel(radioIndex, ext_str);
9226 }
developer06a01d92022-09-07 16:32:39 +08009227 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9228
9229 return RETURN_OK;
9230}
9231
9232INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9233{
developer615510b2022-09-27 10:14:35 +08009234 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009235 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009236 char cmd[256]={0};
9237 char buf[128]={0};
9238 char file_name[32] = {0};
9239 char filter_SSID[32] = {0};
9240 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009241 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009242 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009243 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009244 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009245 size_t len=0;
9246 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009247 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009248 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009249 bool filter_enable = false;
9250 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009251 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009252
developer615510b2022-09-27 10:14:35 +08009253 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009254
developer615510b2022-09-27 10:14:35 +08009255 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9256 f = fopen(file_name, "r");
9257 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009258 fgets(buf, sizeof(file_name), f);
9259 if ((strncmp(buf, "0", 1)) != 0) {
9260 fgets(filter_SSID, sizeof(file_name), f);
9261 if (strlen(filter_SSID) != 0)
9262 filter_enable = true;
9263 }
developer615510b2022-09-27 10:14:35 +08009264 fclose(f);
9265 }
9266
developerac6f1142022-12-20 19:26:35 +08009267 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009268 return RETURN_ERR;
9269
developer033b37b2022-10-18 11:27:46 +08009270 phyId = radio_index_to_phy(radio_index);
9271
9272 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009273 _syscmd(cmd, buf, sizeof(buf));
9274 channels_num = strtol(buf, NULL, 10);
9275
developerd946fd62022-12-08 18:03:28 +08009276 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9277 // 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 +08009278 fprintf(stderr, "cmd: %s\n", cmd);
9279 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009280 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9281 return RETURN_ERR;
9282 }
developer5550e242022-09-30 09:59:32 +08009283
9284 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9285 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9286
developer615510b2022-09-27 10:14:35 +08009287 ret = fgets(line, sizeof(line), f);
9288 while (ret != NULL) {
9289 if(strstr(line, "BSS") != NULL) { // new neighbor info
9290 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9291 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9292 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9293
9294 if (!filter_BSS) {
9295 index++;
9296 wifi_neighbor_ap2_t *tmp;
9297 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9298 if (tmp == NULL) { // no more memory to use
9299 index--;
9300 wifi_dbg_printf("%s: realloc failed\n", __func__);
9301 break;
9302 }
9303 scan_array = tmp;
9304 }
9305 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009306
developer615510b2022-09-27 10:14:35 +08009307 filter_BSS = false;
9308 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9309 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9310 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9311 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9312 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009313 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009314 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009315
developer615510b2022-09-27 10:14:35 +08009316 if (freq >= 2412 && freq <= 2484) {
9317 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9318 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9319 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9320 }
9321 else if (freq >= 5160 && freq <= 5805) {
9322 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9323 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9324 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9325 }
developer06a01d92022-09-07 16:32:39 +08009326
developer615510b2022-09-27 10:14:35 +08009327 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009328 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009329 for (int i = 0; i < channels_num; i++) {
9330 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9331 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9332 break;
9333 }
9334 }
developer06a01d92022-09-07 16:32:39 +08009335 }
developer615510b2022-09-27 10:14:35 +08009336 } else if (strstr(line, "beacon interval") != NULL) {
9337 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9338 } else if (strstr(line, "signal") != NULL) {
9339 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9340 } else if (strstr(line,"SSID") != NULL) {
9341 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9342 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9343 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009344 }
developer615510b2022-09-27 10:14:35 +08009345 } else if (strstr(line, "Supported rates") != NULL) {
9346 char SRate[80] = {0}, *tmp = NULL;
9347 memset(buf, 0, sizeof(buf));
9348 strcpy(SRate, line);
9349 tmp = strtok(SRate, ":");
9350 tmp = strtok(NULL, ":");
9351 strcpy(buf, tmp);
9352 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009353
developer615510b2022-09-27 10:14:35 +08009354 tmp = strtok(buf, " \n");
9355 while (tmp != NULL) {
9356 strcat(SRate, tmp);
9357 if (SRate[strlen(SRate) - 1] == '*') {
9358 SRate[strlen(SRate) - 1] = '\0';
9359 }
9360 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009361
developer615510b2022-09-27 10:14:35 +08009362 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009363 }
developer615510b2022-09-27 10:14:35 +08009364 SRate[strlen(SRate) - 1] = '\0';
9365 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9366 } else if (strstr(line, "DTIM") != NULL) {
9367 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9368 } else if (strstr(line, "VHT capabilities") != NULL) {
9369 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9370 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9371 } else if (strstr(line, "HT capabilities") != NULL) {
9372 strcat(scan_array[index].ap_SupportedStandards, ",n");
9373 strcpy(scan_array[index].ap_OperatingStandards, "n");
9374 } else if (strstr(line, "VHT operation") != NULL) {
9375 ret = fgets(line, sizeof(line), f);
9376 sscanf(line," * channel width: %d", &vht_channel_width);
9377 if(vht_channel_width == 1) {
9378 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9379 } else {
9380 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9381 }
9382 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9383 continue;
9384 } else if (strstr(line, "HT operation") != NULL) {
9385 ret = fgets(line, sizeof(line), f);
9386 sscanf(line," * secondary channel offset: %s", &buf);
9387 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009388 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009389 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 +08009390 }
developer615510b2022-09-27 10:14:35 +08009391 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009392 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009393 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9394 } else {
9395 //20Mhz
9396 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 +08009397 }
developer615510b2022-09-27 10:14:35 +08009398 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009399 continue;
developer615510b2022-09-27 10:14:35 +08009400 } else if (strstr(line, "HE capabilities") != NULL) {
9401 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9402 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9403 ret = fgets(line, sizeof(line), f);
9404 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9405 if (strstr(line, "HE40/2.4GHz") != NULL)
9406 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9407 else
9408 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9409 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9410 if (strstr(line, "HE80/5GHz") != NULL) {
9411 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9412 ret = fgets(line, sizeof(line), f);
9413 } else
9414 continue;
9415 if (strstr(line, "HE160/5GHz") != NULL)
9416 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009417 }
developer615510b2022-09-27 10:14:35 +08009418 continue;
9419 } else if (strstr(line, "WPA") != NULL) {
9420 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9421 } else if (strstr(line, "RSN") != NULL) {
9422 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9423 } else if (strstr(line, "Group cipher") != NULL) {
9424 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9425 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9426 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009427 }
developer06a01d92022-09-07 16:32:39 +08009428 }
developer615510b2022-09-27 10:14:35 +08009429 ret = fgets(line, sizeof(line), f);
9430 }
9431
9432 if (!filter_BSS) {
9433 *output_array_size = index + 1;
9434 } else {
9435 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9436 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009437 }
developer06a01d92022-09-07 16:32:39 +08009438 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009439 pclose(f);
developer5550e242022-09-30 09:59:32 +08009440 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009441 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009442 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009443}
developer615510b2022-09-27 10:14:35 +08009444
developer06a01d92022-09-07 16:32:39 +08009445INT wifi_getApAssociatedDeviceStats(
9446 INT apIndex,
9447 mac_address_t *clientMacAddress,
9448 wifi_associated_dev_stats_t *associated_dev_stats,
9449 u64 *handle)
9450{
9451 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9452 char interface_name[50] = {0};
9453 char cmd[1024] = {0};
9454 char mac_str[18] = {0};
9455 char *key = NULL;
9456 char *val = NULL;
9457 FILE *f = NULL;
9458 char *line = NULL;
9459 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009460
9461 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9462 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9463 return RETURN_ERR;
9464 }
9465
9466 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9467 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9468 if((f = popen(cmd, "r")) == NULL) {
9469 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9470 return RETURN_ERR;
9471 }
9472
developer30423732022-12-01 16:17:49 +08009473 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009474 key = strtok(line,":");
9475 val = strtok(NULL,":");
9476
9477 if(!strncmp(key,"rx bytes",8))
9478 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9479 if(!strncmp(key,"tx bytes",8))
9480 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9481 if(!strncmp(key,"rx packets",10))
9482 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9483 if(!strncmp(key,"tx packets",10))
9484 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9485 if(!strncmp(key,"tx retries",10))
9486 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9487 if(!strncmp(key,"tx failed",9))
9488 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9489 if(!strncmp(key,"rx drop misc",13))
9490 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9491 if(!strncmp(key,"rx bitrate",10)) {
9492 val = strtok(val, " ");
9493 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9494 }
9495 if(!strncmp(key,"tx bitrate",10)) {
9496 val = strtok(val, " ");
9497 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9498 }
9499 }
9500 free(line);
9501 pclose(f);
9502 return RETURN_OK;
9503}
9504
9505INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9506{
developerd946fd62022-12-08 18:03:28 +08009507 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009508 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9509
9510 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9511 if (NULL == output_string)
9512 return RETURN_ERR;
9513
developerac6f1142022-12-20 19:26:35 +08009514 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009515 return RETURN_ERR;
9516 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 +08009517 _syscmd(cmd, buf, sizeof(buf));
9518
9519 //size of SSID name restricted to value less than 32 bytes
9520 snprintf(output_string, 32, "%s", buf);
9521 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9522
9523 return RETURN_OK;
9524}
9525
9526INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9527{
9528 //char cmd[MAX_CMD_SIZE] = {0};
9529 char config_file[MAX_BUF_SIZE] = {0};
9530 char buf[32] = {0};
9531
9532 if (!output_filterMode)
9533 return RETURN_ERR;
9534
9535 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9536 //_syscmd(cmd, buf, sizeof(buf));
9537 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08009538 if (!syn_flag)
9539 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
9540 else
developer07ded1f2024-01-10 10:30:15 +08009541 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer10adcc12022-09-13 14:39:17 +08009542 if(strlen(buf) == 0) {
9543 *output_filterMode = 0;
9544 }
9545 else {
9546 int macaddr_acl_mode = strtol(buf, NULL, 10);
9547 if (macaddr_acl_mode == 1) {
9548 *output_filterMode = 1;
9549 } else if (macaddr_acl_mode == 0) {
9550 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9551 if (strlen(buf) == 0) {
9552 *output_filterMode = 0;
9553 } else {
9554 *output_filterMode = 2;
9555 }
9556 } else {
9557 return RETURN_ERR;
9558 }
9559 }
developer06a01d92022-09-07 16:32:39 +08009560
9561 return RETURN_OK;
9562}
9563
9564INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9565{
9566 FILE *fp = NULL;
9567 char str[MAX_BUF_SIZE] = {0};
9568 int wificlientindex = 0 ;
9569 int count = 0;
9570 int signalstrength = 0;
9571 int arr[MACADDRESS_SIZE] = {0};
9572 unsigned char mac[MACADDRESS_SIZE] = {0};
9573 UINT wifi_count = 0;
9574 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9575 char pipeCmd[MAX_CMD_SIZE] = {0};
9576
9577 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9578 *output_array_size = 0;
9579 *associated_dev_array = NULL;
9580 char interface_name[50] = {0};
9581
9582 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9583 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9584 return RETURN_ERR;
9585 }
9586
9587 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9588 fp = popen(pipeCmd, "r");
9589 if (fp == NULL)
9590 {
9591 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9592 return RETURN_ERR;
9593 }
9594
9595 /* Read the output a line at a time - output it. */
9596 fgets(str, sizeof(str)-1, fp);
9597 wifi_count = (unsigned int) atoi ( str );
9598 *output_array_size = wifi_count;
9599 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9600 pclose(fp);
9601
9602 if(wifi_count == 0)
9603 {
9604 return RETURN_OK;
9605 }
9606 else
9607 {
9608 wifi_associated_dev2_t* temp = NULL;
9609 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9610 *associated_dev_array = temp;
9611 if(temp == NULL)
9612 {
9613 printf("Error Statement. Insufficient memory \n");
9614 return RETURN_ERR;
9615 }
9616
9617 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9618 system(pipeCmd);
9619
9620 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9621 if(fp == NULL)
9622 {
9623 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9624 return RETURN_ERR;
9625 }
9626 fclose(fp);
9627
developer30423732022-12-01 16:17:49 +08009628 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009629 fp = popen(pipeCmd, "r");
9630 if(fp)
9631 {
9632 for(count =0 ; count < wifi_count; count++)
9633 {
9634 fgets(str, MAX_BUF_SIZE, fp);
9635 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9636 {
9637 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9638 {
9639 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9640
9641 }
9642 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9643 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]);
9644 }
9645 temp[count].cli_AuthenticationState = 1; //TODO
9646 temp[count].cli_Active = 1; //TODO
9647 }
9648 pclose(fp);
9649 }
9650
9651 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009652 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 +08009653 fp = popen(pipeCmd, "r");
9654 if(fp)
9655 {
9656 pclose(fp);
9657 }
9658 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9659 if(fp)
9660 {
9661 for(count =0 ; count < wifi_count ;count++)
9662 {
9663 fgets(str, MAX_BUF_SIZE, fp);
9664 signalstrength = atoi(str);
9665 temp[count].cli_RSSI = signalstrength;
9666 }
9667 pclose(fp);
9668 }
9669
9670
9671 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009672 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 +08009673 fp = popen(pipeCmd, "r");
9674 if (fp)
9675 {
9676 pclose(fp);
9677 }
9678 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9679 if (fp)
9680 {
9681 for (count = 0; count < wifi_count; count++)
9682 {
9683 fgets(str, MAX_BUF_SIZE, fp);
9684 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9685 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9686 }
9687 pclose(fp);
9688 }
9689
9690 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009691 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 +08009692 fp = popen(pipeCmd, "r");
9693 if (fp)
9694 {
9695 pclose(fp);
9696 }
9697 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9698 if (fp)
9699 {
9700 for (count = 0; count < wifi_count; count++)
9701 {
9702 fgets(str, MAX_BUF_SIZE, fp);
9703 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9704 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9705 }
9706 pclose(fp);
9707 }
9708 }
9709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9710 return RETURN_OK;
9711
9712}
9713
9714INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9715{
9716#if 0
9717 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009718 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009719 _syscmd(cmd, buf, sizeof(buf));*/
9720
9721 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9722 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9723 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9724 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9725
9726 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.
9727 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].
9728 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].
9729 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].
9730 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9731 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9732
9733 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9734 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9735 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9736 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.
9737 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.
9738 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.
9739 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.
9740 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.
9741 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.
9742 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.
9743 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9744#endif
9745
9746 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009747 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009748 char pipeCmd[128] = {0};
9749 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009750 wifi_ssidTrafficStats2_t *out = output_struct;
9751
developerce736392022-09-13 15:24:34 +08009752 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009753 if (!output_struct)
9754 return RETURN_ERR;
9755
developerce736392022-09-13 15:24:34 +08009756 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009757 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009758 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009759 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009760
developer06a01d92022-09-07 16:32:39 +08009761 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009762 if (fp == NULL) {
9763 fprintf(stderr, "%s: popen failed\n", __func__);
9764 return RETURN_ERR;
9765 }
9766 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009767 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009768
developerce736392022-09-13 15:24:34 +08009769 if (strlen(str) == 0) // interface not exist
9770 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009771
developerce736392022-09-13 15:24:34 +08009772 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9773 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009774
developerce736392022-09-13 15:24:34 +08009775 memset(str, 0, sizeof(str));
9776 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009777 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009778 if (fp == NULL) {
9779 fprintf(stderr, "%s: popen failed\n", __func__);
9780 return RETURN_ERR;
9781 }
9782 fgets(str, sizeof(str), fp);
9783
9784 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9785 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009786 pclose(fp);
developerce736392022-09-13 15:24:34 +08009787
9788 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9789 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9790
9791 // Not supported
9792 output_struct->ssid_RetransCount = 0;
9793 output_struct->ssid_FailedRetransCount = 0;
9794 output_struct->ssid_RetryCount = 0;
9795 output_struct->ssid_MultipleRetryCount = 0;
9796 output_struct->ssid_ACKFailureCount = 0;
9797 output_struct->ssid_AggregatedPacketCount = 0;
9798
developer06a01d92022-09-07 16:32:39 +08009799 return RETURN_OK;
9800}
9801
9802//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).
9803INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9804{
9805 char output_val[16]={'\0'};
9806 char config_file[MAX_BUF_SIZE] = {0};
9807
9808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9809 if (!output)
9810 return RETURN_ERR;
9811 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08009812 if (!syn_flag)
9813 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9814 else
developer07ded1f2024-01-10 10:30:15 +08009815 snprintf(output_val, sizeof(output_val), "%s", vap_info[apIndex].ap_isolate);
developer06a01d92022-09-07 16:32:39 +08009816 if( strcmp(output_val,"1") == 0 )
9817 *output = TRUE;
9818 else
9819 *output = FALSE;
9820 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9821
9822 return RETURN_OK;
9823}
9824
9825INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9826{
9827 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9828 char str[MAX_BUF_SIZE]={'\0'};
9829 char string[MAX_BUF_SIZE]={'\0'};
9830 char cmd[MAX_CMD_SIZE]={'\0'};
9831 char *ch;
9832 char config_file[MAX_BUF_SIZE] = {0};
9833 struct params params;
9834
9835 if(enable == TRUE)
9836 strcpy(string,"1");
9837 else
9838 strcpy(string,"0");
9839
9840 params.name = "ap_isolate";
9841 params.value = string;
9842
9843 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9844 wifi_hostapdWrite(config_file,&params,1);
developerefb790a2023-12-26 18:58:32 +08009845 snprintf(vap_info[apIndex].ap_isolate, sizeof(vap_info[apIndex].ap_isolate), "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08009846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9847
9848 return RETURN_OK;
9849}
9850
9851INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9852{
9853 if (NULL == output_dBm)
9854 return RETURN_ERR;
9855
9856 *output_dBm = 0;
9857 return RETURN_OK;
9858}
9859
9860INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9861{
9862 return RETURN_OK;
9863}
9864INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9865{
9866 return RETURN_OK;
9867}
9868INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9869{
9870 return RETURN_OK;
9871}
9872INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9873{
9874 return RETURN_OK;
9875}
9876INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9877{
9878 return RETURN_OK;
9879}
9880INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9881{
9882 char config_file[MAX_BUF_SIZE] = {0};
9883 struct params list;
9884
9885 list.name = "bss_transition";
9886 list.value = activate?"1":"0";
9887 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9888 wifi_hostapdWrite(config_file, &list, 1);
developerefb790a2023-12-26 18:58:32 +08009889 snprintf(vap_info[apIndex].bss_transition, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08009890
9891 return RETURN_OK;
9892}
9893wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9894
9895void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9896{
9897 return;
9898}
9899
9900INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9901{
9902 // TODO Implement me!
9903 return RETURN_OK;
9904}
9905
9906INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9907{
developera3c68b92022-09-13 15:27:29 +08009908 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009909 FILE *f = NULL;
9910
developer72ec5572023-01-05 16:27:13 +08009911 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009912
developer72ec5572023-01-05 16:27:13 +08009913 if (essid == NULL)
9914 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009915
developer72ec5572023-01-05 16:27:13 +08009916 if (strlen(essid) == 0 || apIndex == -1) {
9917 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9918 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009919 }
9920
developer72ec5572023-01-05 16:27:13 +08009921 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9922 f = fopen(file_name, "w");
9923 if (f == NULL)
9924 return RETURN_ERR;
9925
9926 // For mode == 0 is to disable filter, just don't write ssid to the file.
9927 fprintf(f, "%d\n%s", mode, mode?essid:"");
9928 fclose(f);
9929 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009930 return RETURN_OK;
9931}
9932
9933INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9934{
9935 // TODO Implement me!
9936 //Apply wifi_pushRadioChannel() instantly
9937 return RETURN_ERR;
9938}
9939
9940INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9941{
9942 // TODO Implement me!
9943 return RETURN_OK;
9944}
9945
9946#ifdef HAL_NETLINK_IMPL
9947static int tidStats_callback(struct nl_msg *msg, void *arg) {
9948 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9949 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9950 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9951 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9952 int rem , tid_index = 0;
9953
9954 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9955 wifi_associated_dev_tid_entry_t *stats_entry;
9956
9957 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9958 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9959 };
9960 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9961 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9962 };
9963
9964 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9965 genlmsg_attrlen(gnlh, 0), NULL);
9966
9967
9968 if (!tb[NL80211_ATTR_STA_INFO]) {
9969 fprintf(stderr, "station stats missing!\n");
9970 return NL_SKIP;
9971 }
9972
9973 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9974 tb[NL80211_ATTR_STA_INFO],
9975 stats_policy)) {
9976 fprintf(stderr, "failed to parse nested attributes!\n");
9977 return NL_SKIP;
9978 }
9979
9980 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9981 {
9982 stats_entry = &out->tid_array[tid_index];
9983
9984 stats_entry->tid = tid_index;
9985 stats_entry->ac = _tid_ac_index_get[tid_index];
9986
9987 if(sinfo[NL80211_STA_INFO_TID_STATS])
9988 {
9989 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9990 printf("failed to parse nested stats attributes!");
9991 return NL_SKIP;
9992 }
9993 }
9994 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9995 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9996
9997 if(tid_index < (PS_MAX_TID - 1))
9998 tid_index++;
9999 }
10000 //ToDo: sum_time_ms, ewma_time_ms
10001 return NL_SKIP;
10002}
10003#endif
10004
10005INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
10006{
10007#ifdef HAL_NETLINK_IMPL
10008 Netlink nl;
10009 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010010 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010011
developerac6f1142022-12-20 19:26:35 +080010012 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010013 return RETURN_ERR;
10014
10015 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010016
10017 nl.id = initSock80211(&nl);
10018
10019 if (nl.id < 0) {
10020 fprintf(stderr, "Error initializing netlink \n");
10021 return -1;
10022 }
10023
10024 struct nl_msg* msg = nlmsg_alloc();
10025
10026 if (!msg) {
10027 fprintf(stderr, "Failed to allocate netlink message.\n");
10028 nlfree(&nl);
10029 return -2;
10030 }
10031
10032 genlmsg_put(msg,
10033 NL_AUTO_PORT,
10034 NL_AUTO_SEQ,
10035 nl.id,
10036 0,
10037 0,
10038 NL80211_CMD_GET_STATION,
10039 0);
10040
10041 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10042 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10043 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
10044 nl_send_auto(nl.socket, msg);
10045 nl_recvmsgs(nl.socket, nl.cb);
10046 nlmsg_free(msg);
10047 nlfree(&nl);
10048 return RETURN_OK;
10049#else
10050//iw implementation
10051#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10052#define TOTAL_MAX_LINES 50
10053
10054 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +080010055 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +080010056 FILE *fp=NULL;
10057 char pipeCmd[1024]= {'\0'};
10058 int lines,tid_index=0;
10059 char mac_addr[20] = {'\0'};
10060
developerac6f1142022-12-20 19:26:35 +080010061 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010062 return RETURN_ERR;
10063
developer06a01d92022-09-07 16:32:39 +080010064 wifi_associated_dev_tid_entry_t *stats_entry;
10065
developer06a01d92022-09-07 16:32:39 +080010066 strcpy(mac_addr,clientMacAddress);
10067
10068 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10069 fp= popen(pipeCmd,"r");
10070 if(fp == NULL)
10071 {
10072 perror("popen for station dump failed\n");
10073 return RETURN_ERR;
10074 }
10075 pclose(fp);
10076
10077 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10078 fp=popen(pipeCmd,"r");
10079 if(fp == NULL)
10080 {
10081 perror("popen for grep station failed\n");
10082 return RETURN_ERR;
10083 }
10084 else if(fgets(buf,sizeof(buf),fp) != NULL)
10085 lines=atoi(buf);
10086 else
10087 {
10088 pclose(fp);
10089 fprintf(stderr,"No devices are connected \n");
10090 return RETURN_ERR;
10091 }
10092 pclose(fp);
10093
10094 if(lines == 1)
10095 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10096
10097 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10098 {
10099 stats_entry = &tid_stats->tid_array[tid_index];
10100 stats_entry->tid = tid_index;
10101
10102 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);
10103
10104 fp=popen(pipeCmd,"r");
10105 if(fp ==NULL)
10106 {
10107 perror("Failed to read from tid file \n");
10108 return RETURN_ERR;
10109 }
10110 else if(fgets(buf,sizeof(buf),fp) != NULL)
10111 stats_entry->num_msdus = atol(buf);
10112
10113 pclose(fp);
10114 stats_entry->ac = _tid_ac_index_get[tid_index];
10115// TODO:
10116// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10117// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10118 }
10119 return RETURN_OK;
10120#endif
10121}
10122
10123
10124INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10125{
developerd946fd62022-12-08 18:03:28 +080010126 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +080010127 char cmd[128]={0};
10128 char buf[128]={0};
10129 int freq = 0;
10130
10131 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10132
10133 // full mode is used to scan all channels.
10134 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10135 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10136 ieee80211_channel_to_frequency(chan_list[0], &freq);
10137
developerac6f1142022-12-20 19:26:35 +080010138 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010139 return RETURN_ERR;
10140
developer615510b2022-09-27 10:14:35 +080010141 if (freq)
developerd946fd62022-12-08 18:03:28 +080010142 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +080010143 else
developerd946fd62022-12-08 18:03:28 +080010144 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +080010145
10146 _syscmd(cmd, buf, sizeof(buf));
10147 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10148
developer06a01d92022-09-07 16:32:39 +080010149 return RETURN_OK;
10150}
10151
10152
10153INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10154{
10155 // TODO Implement me!
10156 return RETURN_ERR;
10157}
10158
10159INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10160{
10161 // TODO Implement me!
10162 return RETURN_ERR;
10163}
10164
10165INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10166{
10167 // TODO Implement me!
10168 return RETURN_ERR;
10169}
10170
10171INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10172{
10173 // TODO Implement me!
10174 return RETURN_ERR;
10175}
10176
10177INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10178{
10179 // TODO Implement me!
10180 return RETURN_ERR;
10181}
10182
10183INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10184{
10185 // TODO Implement me!
10186 return RETURN_ERR;
10187}
10188
10189INT wifi_steering_eventUnregister(void)
10190{
10191 // TODO Implement me!
10192 return RETURN_ERR;
10193}
10194
10195INT wifi_delApAclDevices(INT apIndex)
10196{
10197#if 0
10198 char cmd[MAX_BUF_SIZE] = {0};
10199 char buf[MAX_BUF_SIZE] = {0};
10200
10201 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010202 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010203 if(_syscmd(cmd,buf,sizeof(buf)))
10204 return RETURN_ERR;
10205#endif
developer9988c232023-03-06 14:57:08 +080010206 char cmd[256]={0};
10207 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010208
developere6aafda2022-09-13 14:59:28 +080010209 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010210 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 +080010211 if(_syscmd(cmd, buf, sizeof(buf)))
10212 return RETURN_ERR;
10213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010214
10215 return RETURN_OK;
10216}
10217
10218#ifdef HAL_NETLINK_IMPL
10219static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10220 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10221 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10222 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10223 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10224 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10225 char mac_addr[20],dev[20];
10226
10227 nla_parse(tb,
10228 NL80211_ATTR_MAX,
10229 genlmsg_attrdata(gnlh, 0),
10230 genlmsg_attrlen(gnlh, 0),
10231 NULL);
10232
10233 if(!tb[NL80211_ATTR_STA_INFO]) {
10234 fprintf(stderr, "sta stats missing!\n");
10235 return NL_SKIP;
10236 }
10237
10238 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10239 fprintf(stderr, "failed to parse nested attributes!\n");
10240 return NL_SKIP;
10241 }
10242 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10243
10244 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10245
10246 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10247 fprintf(stderr, "failed to parse nested rate attributes!");
10248 return NL_SKIP;
10249 }
10250
10251 if(sinfo[NL80211_STA_INFO_TID_STATS])
10252 {
10253 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10254 printf("failed to parse nested stats attributes!");
10255 return NL_SKIP;
10256 }
10257 }
10258
10259 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10260 {
10261 printf("Type is VHT\n");
10262 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10263 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10264
10265 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10266 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10267 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10268 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10269 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10270 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10271 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10272 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10273 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10274 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10275 }
10276 else
10277 {
10278 printf(" OFDM or CCK \n");
10279 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10280 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10281 }
10282
10283 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10284 if(rinfo[NL80211_RATE_INFO_MCS])
10285 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10286 }
10287 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10288 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10289 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10290 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10291
10292 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10293 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10294
10295 if (sinfo[NL80211_STA_INFO_SIGNAL])
10296 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10297 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10298 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10299 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10300 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10301 //rssi_array need to be filled
10302 return NL_SKIP;
10303}
10304#endif
10305
10306INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10307{
10308#ifdef HAL_NETLINK_IMPL
10309 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010310 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010311 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010312 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010313
10314 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10315
10316 if (*output_array_size <= 0)
10317 return RETURN_OK;
10318
developer06a01d92022-09-07 16:32:39 +080010319 nl.id = initSock80211(&nl);
10320
10321 if (nl.id < 0) {
10322 fprintf(stderr, "Error initializing netlink \n");
10323 return 0;
10324 }
10325
10326 struct nl_msg* msg = nlmsg_alloc();
10327
10328 if (!msg) {
10329 fprintf(stderr, "Failed to allocate netlink message.\n");
10330 nlfree(&nl);
10331 return 0;
10332 }
10333
10334 genlmsg_put(msg,
10335 NL_AUTO_PORT,
10336 NL_AUTO_SEQ,
10337 nl.id,
10338 0,
10339 0,
10340 NL80211_CMD_GET_STATION,
10341 0);
10342
10343 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10344 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10345 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10346 nl_send_auto(nl.socket, msg);
10347 nl_recvmsgs(nl.socket, nl.cb);
10348 nlmsg_free(msg);
10349 nlfree(&nl);
10350 return RETURN_OK;
10351#else
10352 //TODO Implement me
10353 return RETURN_OK;
10354#endif
10355}
10356
10357#ifdef HAL_NETLINK_IMPL
10358static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10359 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10360 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10361 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10362 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10363 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10364 char mac_addr[20],dev[20];
10365
10366 nla_parse(tb,
10367 NL80211_ATTR_MAX,
10368 genlmsg_attrdata(gnlh, 0),
10369 genlmsg_attrlen(gnlh, 0),
10370 NULL);
10371
10372 if(!tb[NL80211_ATTR_STA_INFO]) {
10373 fprintf(stderr, "sta stats missing!\n");
10374 return NL_SKIP;
10375 }
10376
10377 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10378 fprintf(stderr, "failed to parse nested attributes!\n");
10379 return NL_SKIP;
10380 }
10381
10382 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10383
10384 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10385
10386 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10387 fprintf(stderr, "failed to parse nested rate attributes!");
10388 return NL_SKIP;
10389 }
10390
10391 if(sinfo[NL80211_STA_INFO_TID_STATS])
10392 {
10393 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10394 printf("failed to parse nested stats attributes!");
10395 return NL_SKIP;
10396 }
10397 }
10398 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10399 {
10400 printf("Type is VHT\n");
10401 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10402 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10403
10404 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10405 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10406 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10407 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10408 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10409 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10410 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10411 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10412 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10413 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10414 }
10415 else
10416 {
10417 printf(" OFDM or CCK \n");
10418 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10419 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10420 }
10421
10422 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10423 if(rinfo[NL80211_RATE_INFO_MCS])
10424 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10425 }
10426
10427 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10428 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10429 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10430 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10431
10432 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10433 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10434 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10435
10436 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10437 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10438
10439 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10440 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10441
10442 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10443 ((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]);
10444
10445 return NL_SKIP;
10446}
10447#endif
10448
10449INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10450{
10451#ifdef HAL_NETLINK_IMPL
10452 Netlink nl;
10453 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010454 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010455 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010456 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010457
10458 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10459
10460 if (*output_array_size <= 0)
10461 return RETURN_OK;
10462
developerd946fd62022-12-08 18:03:28 +080010463 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010464
10465 nl.id = initSock80211(&nl);
10466
10467 if(nl.id < 0) {
10468 fprintf(stderr, "Error initializing netlink \n");
10469 return 0;
10470 }
10471
10472 struct nl_msg* msg = nlmsg_alloc();
10473
10474 if(!msg) {
10475 fprintf(stderr, "Failed to allocate netlink message.\n");
10476 nlfree(&nl);
10477 return 0;
10478 }
10479
10480 genlmsg_put(msg,
10481 NL_AUTO_PORT,
10482 NL_AUTO_SEQ,
10483 nl.id,
10484 0,
10485 0,
10486 NL80211_CMD_GET_STATION,
10487 0);
10488
10489 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10490 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10491 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10492 nl_send_auto(nl.socket, msg);
10493 nl_recvmsgs(nl.socket, nl.cb);
10494 nlmsg_free(msg);
10495 nlfree(&nl);
10496 return RETURN_OK;
10497#else
10498 //TODO Implement me
10499 return RETURN_OK;
10500#endif
10501}
10502
10503INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10504{
10505 // TODO Implement me!
10506 char buf[MAX_BUF_SIZE] = {0};
10507 char config_file[MAX_BUF_SIZE] = {0};
10508
10509 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +080010510 if (!syn_flag)
10511 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10512 else
developer07ded1f2024-01-10 10:30:15 +080010513 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].bss_transition);
developer06a01d92022-09-07 16:32:39 +080010514 *activate = (strncmp("1",buf,1) == 0);
10515
10516 return RETURN_OK;
10517}
10518
10519INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10520{
10521 char config_file[MAX_BUF_SIZE] = {0};
10522 struct params list;
10523
10524 list.name = "rrm_neighbor_report";
10525 list.value = activate?"1":"0";
10526 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10527 wifi_hostapdWrite(config_file, &list, 1);
10528
10529 return RETURN_OK;
10530}
10531
10532INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10533{
10534 char buf[32] = {0};
10535 char config_file[MAX_BUF_SIZE] = {0};
10536
10537 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10538 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10539 *activate = (strncmp("1",buf,1) == 0);
10540
10541 return RETURN_OK;
10542}
10543#undef HAL_NETLINK_IMPL
10544#ifdef HAL_NETLINK_IMPL
10545static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10546 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10547 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10548 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10549 char dev[20];
10550 int freq =0 ;
10551 static int i=0;
10552
10553 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10554
10555 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10556 };
10557
10558 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10559
10560 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10561
10562 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10563 fprintf(stderr, "survey data missing!\n");
10564 return NL_SKIP;
10565 }
10566
10567 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10568 {
10569 fprintf(stderr, "failed to parse nested attributes!\n");
10570 return NL_SKIP;
10571 }
10572
10573
10574 if(out[0].array_size == 1 )
10575 {
10576 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10577 {
10578 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10579 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10580 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10581
10582 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10583 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10584 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10585 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10586 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10587 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10588 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10589 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10590 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10591 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10592 if (sinfo[NL80211_SURVEY_INFO_TIME])
10593 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10594 return NL_STOP;
10595 }
10596 }
10597 else
10598 {
10599 if ( i <= out[0].array_size )
10600 {
10601 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10602 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10603 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10604
10605 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10606 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10607 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10608 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10609 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10610 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10611 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10612 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10613 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10614 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10615 if (sinfo[NL80211_SURVEY_INFO_TIME])
10616 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10617 }
10618 }
10619
10620 i++;
10621 return NL_SKIP;
10622}
10623#endif
10624
10625static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10626{
10627 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10628 FILE *fp;
10629
10630 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10631 {
10632 printf("Creating Frequency-Channel Map\n");
10633 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10634 }
10635 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10636 if((fp = popen(command, "r")))
10637 {
10638 fgets(output, sizeof(output), fp);
10639 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010640 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010641 }
10642
10643 return 0;
10644}
10645
10646static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10647{
10648 int freqMHz = -1;
10649 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010650 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010651
10652 ieee80211_channel_to_frequency(channel, &freqMHz);
10653 if (freqMHz == -1) {
10654 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10655 return -1;
10656 }
10657
developer7930d352022-12-21 17:55:42 +080010658 wifi_GetInterfaceName(radioIndex, interface_name);
10659 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010660 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10661 radioIndex, freqMHz);
10662 return -1;
10663 }
10664
10665 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10666 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10667 return -1;
10668 }
10669
10670 return 0;
10671}
10672
10673static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10674{
10675 const char *ptr = buf;
10676 char *key = NULL;
10677 char *val = NULL;
10678 char line[256] = { '\0' };
10679
10680 while (ptr = get_line_from_str_buf(ptr, line)) {
10681 if (strstr(line, "Frequency")) continue;
10682
10683 key = strtok(line, ":");
10684 val = strtok(NULL, " ");
10685 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10686
10687 if (!strcmp(key, "noise")) {
10688 sscanf(val, "%d", &stats->ch_noise);
10689 if (stats->ch_noise == 0) {
10690 // Workaround for missing noise information.
10691 // Assume -95 for 2.4G and -103 for 5G
10692 if (radioIndex == 0) stats->ch_noise = -95;
10693 if (radioIndex == 1) stats->ch_noise = -103;
10694 }
10695 }
10696 else if (!strcmp(key, "channel active time")) {
10697 sscanf(val, "%llu", &stats->ch_utilization_total);
10698 }
10699 else if (!strcmp(key, "channel busy time")) {
10700 sscanf(val, "%llu", &stats->ch_utilization_busy);
10701 }
10702 else if (!strcmp(key, "channel receive time")) {
10703 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10704 }
10705 else if (!strcmp(key, "channel transmit time")) {
10706 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10707 }
10708 };
10709
10710 return 0;
10711}
10712
10713INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10714{
10715 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10716#ifdef HAL_NETLINK_IMPL
10717 Netlink nl;
10718 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010719 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010720
10721 local[0].array_size = array_size;
10722
developerac6f1142022-12-20 19:26:35 +080010723 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010724 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010725
10726 nl.id = initSock80211(&nl);
10727
10728 if (nl.id < 0) {
10729 fprintf(stderr, "Error initializing netlink \n");
10730 return -1;
10731 }
10732
10733 struct nl_msg* msg = nlmsg_alloc();
10734
10735 if (!msg) {
10736 fprintf(stderr, "Failed to allocate netlink message.\n");
10737 nlfree(&nl);
10738 return -2;
10739 }
10740
10741 genlmsg_put(msg,
10742 NL_AUTO_PORT,
10743 NL_AUTO_SEQ,
10744 nl.id,
10745 0,
10746 NLM_F_DUMP,
10747 NL80211_CMD_GET_SURVEY,
10748 0);
10749
10750 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10751 nl_send_auto(nl.socket, msg);
10752 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10753 nl_recvmsgs(nl.socket, nl.cb);
10754 nlmsg_free(msg);
10755 nlfree(&nl);
10756 //Copying the Values
10757 for(int i=0;i<array_size;i++)
10758 {
10759 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10760 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10761 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10762 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10763 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10764 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10765 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10766 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10767 }
10768#else
10769 ULONG channel = 0;
10770 int i;
10771 int number_of_channels = array_size;
10772 char buf[512];
10773 INT ret;
10774 wifi_channelStats_t tmp_stats;
10775
10776 if (number_of_channels == 0) {
10777 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10778 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10779 return RETURN_ERR;
10780 }
10781 number_of_channels = 1;
10782 input_output_channelStats_array[0].ch_number = channel;
10783 }
10784
10785 for (i = 0; i < number_of_channels; i++) {
10786
10787 input_output_channelStats_array[i].ch_noise = 0;
10788 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10789 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10790 input_output_channelStats_array[i].ch_utilization_busy = 0;
10791 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10792 input_output_channelStats_array[i].ch_utilization_total = 0;
10793
10794 memset(buf, 0, sizeof(buf));
10795 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10796 return RETURN_ERR;
10797 }
10798 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10799 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10800 return RETURN_ERR;
10801 }
10802
10803 // XXX: fake missing 'self' counter which is not available in iw survey output
10804 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10805 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10806
10807 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10808 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10809 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10810 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10811 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10812
10813 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",
10814 __func__,
10815 input_output_channelStats_array[i].ch_number,
10816 input_output_channelStats_array[i].ch_noise,
10817 input_output_channelStats_array[i].ch_utilization_total,
10818 input_output_channelStats_array[i].ch_utilization_busy,
10819 input_output_channelStats_array[i].ch_utilization_busy_rx,
10820 input_output_channelStats_array[i].ch_utilization_busy_tx,
10821 input_output_channelStats_array[i].ch_utilization_busy_self,
10822 input_output_channelStats_array[i].ch_utilization_busy_ext);
10823 }
10824#endif
10825 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10826 return RETURN_OK;
10827}
10828#define HAL_NETLINK_IMPL
10829
10830/* Hostapd events */
10831
10832#ifndef container_of
10833#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10834#define container_of(ptr, type, member) \
10835 ((type *)((char *)ptr - offset_of(type, member)))
10836#endif /* container_of */
10837
10838struct ctrl {
10839 char sockpath[128];
10840 char sockdir[128];
10841 char bss[IFNAMSIZ];
10842 char reply[4096];
10843 int ssid_index;
10844 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10845 void (*overrun)(struct ctrl *ctrl);
10846 struct wpa_ctrl *wpa;
10847 unsigned int ovfl;
10848 size_t reply_len;
10849 int initialized;
10850 ev_timer retry;
10851 ev_timer watchdog;
10852 ev_stat stat;
10853 ev_io io;
10854};
10855static wifi_newApAssociatedDevice_callback clients_connect_cb;
10856static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10857static struct ctrl wpa_ctrl[MAX_APS];
10858static int initialized;
10859
10860static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10861{
10862 char cbuf[256] = {};
10863 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10864 struct cmsghdr *cmsg;
10865 unsigned int ovfl = ctrl->ovfl;
10866 unsigned int drop;
10867
10868 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10869 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10870 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10871 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10872
10873 drop = ovfl - ctrl->ovfl;
10874 ctrl->ovfl = ovfl;
10875
10876 return drop;
10877}
10878
10879static void ctrl_close(struct ctrl *ctrl)
10880{
10881 if (ctrl->io.cb)
10882 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10883 if (ctrl->retry.cb)
10884 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10885 if (!ctrl->wpa)
10886 return;
10887
10888 wpa_ctrl_detach(ctrl->wpa);
10889 wpa_ctrl_close(ctrl->wpa);
10890 ctrl->wpa = NULL;
10891 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10892}
10893
10894static void ctrl_process(struct ctrl *ctrl)
10895{
10896 const char *str;
10897 int drops;
10898 int level;
10899 int err;
10900
10901 /* Example events:
10902 *
10903 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10904 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10905 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10906 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10907 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10908 */
10909 if (!(str = index(ctrl->reply, '>')))
10910 return;
10911 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10912 return;
10913
10914 str++;
10915
10916 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10917 if (!(str = index(ctrl->reply, ' ')))
10918 return;
10919 wifi_associated_dev_t sta;
10920 memset(&sta, 0, sizeof(sta));
10921
10922 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10923 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10924 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10925
10926 sta.cli_Active=true;
10927
10928 (clients_connect_cb)(ctrl->ssid_index, &sta);
10929 goto handled;
10930 }
10931
10932 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10933 if (!(str = index(ctrl->reply, ' ')))
10934 return;
10935
10936 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10937 goto handled;
10938 }
10939
10940 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10941 printf("CTRL_WPA: handle TERMINATING event\n");
10942 goto retry;
10943 }
10944
10945 if (strncmp("AP-DISABLED", str, 11) == 0) {
10946 printf("CTRL_WPA: handle AP-DISABLED\n");
10947 goto retry;
10948 }
10949
10950 printf("Event not supported!!\n");
10951
10952handled:
10953
10954 if ((drops = ctrl_get_drops(ctrl))) {
10955 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10956 if (ctrl->overrun)
10957 ctrl->overrun(ctrl);
10958 }
10959
10960 return;
10961
10962retry:
10963 printf("WPA_CTRL: closing\n");
10964 ctrl_close(ctrl);
10965 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10966 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10967}
10968
10969static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10970{
10971 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10972 int err;
10973
10974 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10975 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10976 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10977 ctrl->reply[ctrl->reply_len] = 0;
10978 if (err < 0) {
10979 if (errno == EAGAIN || errno == EWOULDBLOCK)
10980 return;
10981 ctrl_close(ctrl);
10982 ev_timer_again(EV_A_ &ctrl->retry);
10983 return;
10984 }
10985
10986 ctrl_process(ctrl);
10987}
10988
10989static int ctrl_open(struct ctrl *ctrl)
10990{
10991 int fd;
10992
10993 if (ctrl->wpa)
10994 return 0;
10995
10996 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10997 if (!ctrl->wpa)
10998 goto err;
10999
11000 if (wpa_ctrl_attach(ctrl->wpa) < 0)
11001 goto err_close;
11002
11003 fd = wpa_ctrl_get_fd(ctrl->wpa);
11004 if (fd < 0)
11005 goto err_detach;
11006
11007 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
11008 goto err_detach;
11009
11010 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11011 ev_io_start(EV_DEFAULT_ &ctrl->io);
11012
11013 return 0;
11014
11015err_detach:
11016 wpa_ctrl_detach(ctrl->wpa);
11017err_close:
11018 wpa_ctrl_close(ctrl->wpa);
11019err:
11020 ctrl->wpa = NULL;
11021 return -1;
11022}
11023
11024static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11025{
11026 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11027
11028 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11029 ctrl_open(ctrl);
11030}
11031
11032static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11033{
11034 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11035
11036 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11037 if (ctrl_open(ctrl) == 0) {
11038 printf("WPA_CTRL: retry successful\n");
11039 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11040 }
11041}
11042
11043int ctrl_enable(struct ctrl *ctrl)
11044{
11045 if (ctrl->wpa)
11046 return 0;
11047
11048 if (!ctrl->stat.cb) {
11049 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11050 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11051 }
11052
11053 if (!ctrl->retry.cb) {
11054 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11055 }
11056
11057 return ctrl_open(ctrl);
11058}
11059
11060static void
11061ctrl_msg_cb(char *buf, size_t len)
11062{
11063 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11064
11065 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11066 ctrl_process(ctrl);
11067}
11068
11069static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11070{
11071 int err;
11072
11073 if (!ctrl->wpa)
11074 return -1;
11075 if (*reply_len < 2)
11076 return -1;
11077
11078 (*reply_len)--;
11079 ctrl->reply_len = sizeof(ctrl->reply);
11080 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11081 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11082 if (err < 0)
11083 return err;
11084
11085 if (ctrl->reply_len > *reply_len)
11086 ctrl->reply_len = *reply_len;
11087
11088 *reply_len = ctrl->reply_len;
11089 memcpy(reply, ctrl->reply, *reply_len);
11090 reply[*reply_len - 1] = 0;
11091 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11092 return 0;
11093}
11094
11095static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11096{
11097 const char *pong = "PONG";
11098 const char *ping = "PING";
11099 char reply[1024];
11100 size_t len = sizeof(reply);
11101 int err;
11102 ULONG s, snum;
11103 INT ret;
11104 BOOL status;
11105
11106 printf("WPA_CTRL: watchdog cb\n");
11107
11108 ret = wifi_getSSIDNumberOfEntries(&snum);
11109 if (ret != RETURN_OK) {
11110 printf("%s: failed to get SSID count", __func__);
11111 return;
11112 }
11113
11114 if (snum > MAX_APS) {
11115 printf("more ssid than supported! %lu\n", snum);
11116 return;
11117 }
11118
11119 for (s = 0; s < snum; s++) {
11120 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080011121 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080011122 continue;
11123 }
11124 if (status == false) continue;
11125
11126 memset(reply, 0, sizeof(reply));
11127 len = sizeof(reply);
11128 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11129 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11130 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11131 continue;
11132
11133 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11134 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080011135 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080011136 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11137 }
11138}
11139
11140static int init_wpa()
11141{
11142 int ret = 0, i = 0;
11143 ULONG s, snum;
11144
11145 ret = wifi_getSSIDNumberOfEntries(&snum);
11146 if (ret != RETURN_OK) {
11147 printf("%s: failed to get SSID count", __func__);
11148 return RETURN_ERR;
11149 }
11150
11151 if (snum > MAX_APS) {
11152 printf("more ssid than supported! %lu\n", snum);
11153 return RETURN_ERR;
11154 }
11155
11156 for (s = 0; s < snum; s++) {
11157 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11158 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11159 wpa_ctrl[s].ssid_index = s;
11160 ctrl_enable(&wpa_ctrl[s]);
11161 }
11162
11163 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11164 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11165
11166 initialized = 1;
11167 printf("WPA_CTRL: initialized\n");
11168
11169 return RETURN_OK;
11170}
11171
11172void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11173{
11174 clients_connect_cb = callback_proc;
11175 if (!initialized)
11176 init_wpa();
11177}
11178
11179void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11180{
11181 clients_disconnect_cb = callback_proc;
11182 if (!initialized)
11183 init_wpa();
11184}
11185
11186INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11187{
11188 // TODO Implement me!
11189 return RETURN_ERR;
11190}
11191
11192INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11193{
11194 // TODO Implement me!
11195 return RETURN_ERR;
11196}
11197
11198INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11199{
11200 int i;
developer4b102122023-02-15 10:53:03 +080011201 int phyId = -1;
11202 char cmd[256] = {0};
11203 char channel_numbers_buf[256] = {0};
11204 char dfs_state_buf[256] = {0};
11205 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011206 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011207 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080011208
developer4b102122023-02-15 10:53:03 +080011209 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011210
developer4b102122023-02-15 10:53:03 +080011211 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11212 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011213
developer4b102122023-02-15 10:53:03 +080011214 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 +080011215
developer4b102122023-02-15 10:53:03 +080011216 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11217 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11218 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011219 }
11220
developer4b102122023-02-15 10:53:03 +080011221 ptr = channel_numbers_buf;
11222 i = 0;
11223 while (ptr = get_line_from_str_buf(ptr, line)) {
11224 if (i >= outputMapSize) {
11225 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11226 return RETURN_ERR;
11227 }
11228 sscanf(line, "%d", &outputMap[i].ch_number);
11229
11230 memset(cmd, 0, sizeof(cmd));
11231 // Below command should fetch string for DFS state (usable, available or unavailable)
11232 // Example line: "DFS state: usable (for 78930 sec)"
11233 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) {
11234 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011235 return RETURN_ERR;
11236 }
11237
developer4b102122023-02-15 10:53:03 +080011238 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11239 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011240 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11241 return RETURN_ERR;
11242 }
11243
developer4b102122023-02-15 10:53:03 +080011244 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011245
developer4b102122023-02-15 10:53:03 +080011246 if (!strcmp(dfs_state_buf, "usable")) {
11247 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11248 } else if (!strcmp(dfs_state_buf, "available")) {
11249 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11250 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11251 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11252 } else {
11253 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011254 }
developer4b102122023-02-15 10:53:03 +080011255 i++;
developer06a01d92022-09-07 16:32:39 +080011256 }
11257
developer4b102122023-02-15 10:53:03 +080011258 return RETURN_OK;
11259
developer06a01d92022-09-07 16:32:39 +080011260 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11261 return RETURN_ERR;
11262}
11263
11264INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11265{
11266 // TODO Implement me!
11267 return RETURN_ERR;
11268}
11269
11270INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11271{
11272 return RETURN_OK;
11273}
11274
11275INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11276{
11277 // TODO Implement me!
11278 return RETURN_ERR;
11279}
11280
11281INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11282{
11283 // TODO API refrence Implementaion is present on RPI hal
11284 return RETURN_ERR;
11285}
11286
developerfeab1d12023-09-27 11:29:38 +080011287
developer06a01d92022-09-07 16:32:39 +080011288INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11289{
developera5005b62022-09-13 15:43:35 +080011290 char cmd[128]={'\0'};
11291 char buf[128]={'\0'};
developerfeab1d12023-09-27 11:29:38 +080011292 int radioIndex = -1;
11293 int phyIndex = -1;
11294 bool enabled = false;
11295 int cur_tx_dbm = 0;
developera5005b62022-09-13 15:43:35 +080011296
11297 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfeab1d12023-09-27 11:29:38 +080011298
developera5005b62022-09-13 15:43:35 +080011299 if(txpwr_pcntg == NULL)
11300 return RETURN_ERR;
11301
developerfeab1d12023-09-27 11:29:38 +080011302 // The API name as getRadioXXX, I think the input index should be radioIndex,
11303 // but current we not change the name, but use it as radioIndex
11304 radioIndex = apIndex;
11305 phyIndex = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +080011306
developera5005b62022-09-13 15:43:35 +080011307 // Get the maximum tx power of the device
developerfeab1d12023-09-27 11:29:38 +080011308 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11309 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011310 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011311 if (strcmp(buf, "enable") == 0)
11312 enabled = true;
developera5005b62022-09-13 15:43:35 +080011313
developerfeab1d12023-09-27 11:29:38 +080011314 if (!enabled) {
11315 *txpwr_pcntg = 100;
11316 return RETURN_OK;
11317 }
11318
developera5005b62022-09-13 15:43:35 +080011319 memset(cmd, 0, sizeof(cmd));
11320 memset(buf, 0, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011321 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11322 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011323 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011324 cur_tx_dbm = strtol(buf, NULL, 10);
developera5005b62022-09-13 15:43:35 +080011325
developerfeab1d12023-09-27 11:29:38 +080011326 switch (cur_tx_dbm) {
11327 case 0:
11328 *txpwr_pcntg = 100; // range 91-100
developera5005b62022-09-13 15:43:35 +080011329 break;
developerfeab1d12023-09-27 11:29:38 +080011330 case 1:
11331 *txpwr_pcntg = 75; // range 61-90
11332 break;
11333 case 3:
11334 *txpwr_pcntg = 50; // range 31-60
11335 break;
11336 case 6:
11337 *txpwr_pcntg = 25; // range 16-30
11338 break;
11339 case 9:
11340 *txpwr_pcntg = 12; // range 10-15
11341 break;
11342 case 12:
11343 *txpwr_pcntg = 6; // range 1-9
11344 break;
11345 default:
11346 *txpwr_pcntg = 100; // 0
developera5005b62022-09-13 15:43:35 +080011347 }
developerfeab1d12023-09-27 11:29:38 +080011348
developer06a01d92022-09-07 16:32:39 +080011349 return RETURN_OK;
11350}
11351
11352INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11353{
developer58599c22022-09-13 16:40:34 +080011354 // TODO precac feature.
11355 struct params params = {0};
11356 char config_file[128] = {0};
11357
11358 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11359
11360 params.name = "enable_background_radar";
11361 params.value = enable?"1":"0";
11362 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11363 wifi_hostapdWrite(config_file, &params, 1);
11364 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11365
11366 /* TODO precac feature */
11367
11368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11369 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011370}
11371
11372INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11373{
developer58599c22022-09-13 16:40:34 +080011374 char config_file[128] = {0};
11375 char buf[64] = {0};
11376
11377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11378 if (NULL == enable || NULL == precac)
11379 return RETURN_ERR;
11380
11381 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11382 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011383 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011384 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011385 *precac = true;
11386 } else {
developer58599c22022-09-13 16:40:34 +080011387 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011388 *precac = false;
11389 }
developer58599c22022-09-13 16:40:34 +080011390
11391 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11392 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011393}
11394
11395INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11396{
developer58599c22022-09-13 16:40:34 +080011397 *supported = TRUE;
11398 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011399}
11400
developera7149722023-01-11 11:36:21 +080011401bool check_is_hemu_vendor_new_patch() {
11402 char cmd[128] = {0};
11403 char buf[128] = {0};
11404
11405 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11406 _syscmd(cmd, buf, sizeof(buf));
11407
11408 if (strlen(buf) > 0)
11409 return FALSE;
11410 else
11411 return TRUE;
11412}
11413
developer3e6b1692022-09-30 18:04:05 +080011414INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11415{
11416 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11417 struct params params = {0};
11418 char config_file[64] = {0};
11419 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011420 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011421 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011422 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011423 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11424
developera7149722023-01-11 11:36:21 +080011425 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011426
11427 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11428 set_mu_type &= ~0x05; // unset bit 0, 2
11429 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11430 set_mu_type |= 0x01;
11431 set_mu_type &= ~0x04;
11432 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11433 set_mu_type &= ~0x01;
11434 set_mu_type |= 0x04;
11435 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11436 set_mu_type |= 0x05; // set bit 0, 2
11437 }
11438
developera7149722023-01-11 11:36:21 +080011439 new_vendor_patch = check_is_hemu_vendor_new_patch();
11440 if (new_vendor_patch)
11441 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11442 else
11443 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11444
11445 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011446 sprintf(buf, "%u", set_mu_type);
11447 params.value = buf;
11448 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11449 wifi_hostapdWrite(config_file, &params, 1);
11450 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011451 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011452
11453 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11454 return RETURN_OK;
11455}
11456
11457INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11458{
11459 struct params params={0};
11460 char config_file[64] = {0};
11461 char buf[64] = {0};
11462 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011463 bool new_vendor_patch = FALSE;
11464 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011465
11466 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11467
11468 if (mu_type == NULL)
11469 return RETURN_ERR;
11470
developera7149722023-01-11 11:36:21 +080011471 new_vendor_patch = check_is_hemu_vendor_new_patch();
11472
11473 if (new_vendor_patch)
11474 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11475 else
11476 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11477
developer3e6b1692022-09-30 18:04:05 +080011478 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011479 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011480 get_mu_type = strtol(buf, NULL, 10);
11481
11482 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11483 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11484 else if (get_mu_type & 0x04)
11485 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11486 else if (get_mu_type & 0x01)
11487 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11488 else
11489 *mu_type = WIFI_DL_MU_TYPE_NONE;
11490
11491 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11492 return RETURN_OK;
11493}
11494
11495INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11496{
11497 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11498 struct params params={0};
11499 char config_file[64] = {0};
11500 char buf[64] = {0};
11501 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011502 bool new_vendor_patch = FALSE;
11503 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011504 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11505
developera7149722023-01-11 11:36:21 +080011506 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011507
11508 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11509 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11510 set_mu_type &= ~0x0a;
11511 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11512 set_mu_type |= 0x02;
11513 set_mu_type &= ~0x08;
11514 }
11515
developera7149722023-01-11 11:36:21 +080011516 new_vendor_patch = check_is_hemu_vendor_new_patch();
11517
11518 if (new_vendor_patch)
11519 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11520 else
11521 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11522
11523 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011524 sprintf(buf, "%u", set_mu_type);
11525 params.value = buf;
11526 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11527 wifi_hostapdWrite(config_file, &params, 1);
11528 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011529 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011530
11531 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11532 return RETURN_OK;
11533}
11534
11535INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11536{
11537 struct params params={0};
11538 char config_file[64] = {0};
11539 char buf[64] = {0};
11540 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011541 bool new_vendor_patch = FALSE;
11542 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011543
11544 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11545
developera7149722023-01-11 11:36:21 +080011546 new_vendor_patch = check_is_hemu_vendor_new_patch();
11547
11548 if (new_vendor_patch)
11549 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11550 else
11551 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11552
developer3e6b1692022-09-30 18:04:05 +080011553 if (mu_type == NULL)
11554 return RETURN_ERR;
11555
11556 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011557 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011558
11559 get_mu_type = strtol(buf, NULL, 10);
11560 if (get_mu_type & 0x02)
11561 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11562 else
11563 *mu_type = WIFI_DL_MU_TYPE_NONE;
11564
11565 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11566 return RETURN_OK;
11567}
11568
11569
developer454b9462022-09-13 15:29:16 +080011570INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11571{
11572 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011573 char buf[256] = {0};
11574 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011575 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011576 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011577 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011578 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011579
11580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11581
developer254882b2022-09-30 17:12:31 +080011582 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011583 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11584 return RETURN_ERR;
11585 }
developer454b9462022-09-13 15:29:16 +080011586
developer254882b2022-09-30 17:12:31 +080011587 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011588 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011589
developer254882b2022-09-30 17:12:31 +080011590 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11591 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011592 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011593 _syscmd(cmd, buf, sizeof(buf));
11594 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11595 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11596 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011597 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 +080011598 _syscmd(cmd, buf, sizeof(buf));
11599 }
11600 if (band == band_5) {
11601 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11602 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011603 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 +080011604 _syscmd(cmd, buf, sizeof(buf));
11605 }
11606 }
11607 }
11608 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011609
developer254882b2022-09-30 17:12:31 +080011610 if (guard_interval == wifi_guard_interval_400)
11611 strcpy(GI, "0.4");
11612 else if (guard_interval == wifi_guard_interval_800)
11613 strcpy(GI, "0.8");
11614 else if (guard_interval == wifi_guard_interval_1600)
11615 strcpy(GI, "1.6");
11616 else if (guard_interval == wifi_guard_interval_3200)
11617 strcpy(GI, "3.2");
11618 else if (guard_interval == wifi_guard_interval_auto)
11619 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011620 // Record GI for get GI function
11621 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11622 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011623 if (f == NULL)
11624 return RETURN_ERR;
11625 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011626 fclose(f);
11627 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11628 return RETURN_OK;
11629}
11630
11631INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11632{
11633 char buf[32] = {0};
11634 char cmd[64] = {0};
11635
11636 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11637
11638 if (guard_interval == NULL)
11639 return RETURN_ERR;
11640
developer7c4cd202023-03-01 10:56:29 +080011641 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011642 _syscmd(cmd, buf, sizeof(buf));
11643
11644 if (strncmp(buf, "0.4", 3) == 0)
11645 *guard_interval = wifi_guard_interval_400;
11646 else if (strncmp(buf, "0.8", 3) == 0)
11647 *guard_interval = wifi_guard_interval_800;
11648 else if (strncmp(buf, "1.6", 3) == 0)
11649 *guard_interval = wifi_guard_interval_1600;
11650 else if (strncmp(buf, "3.2", 3) == 0)
11651 *guard_interval = wifi_guard_interval_3200;
11652 else
11653 *guard_interval = wifi_guard_interval_auto;
11654
11655 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11656 return RETURN_OK;
11657}
11658
developer3cc61d12022-09-13 16:36:05 +080011659INT wifi_setBSSColor(INT radio_index, UCHAR color)
11660{
11661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11662 struct params params = {0};
11663 char config_file[128] = {0};
11664 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011665 UCHAR *color_list;
11666 int color_num = 0;
11667 int maxNumberColors = 64;
11668 BOOL color_is_aval = FALSE;
11669
developerbf0b9dc2023-07-06 14:30:54 +080011670 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011671 return RETURN_ERR;
11672
developer517f3be2023-05-08 10:02:39 +080011673 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11674 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11675 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011676 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011677 }
developer2acb9632023-03-14 14:58:31 +080011678
11679 for (int i = 0; i < color_num; i++) {
11680 if (color_list[i] == color) {
11681 color_is_aval = TRUE;
11682 break;
11683 }
11684 }
11685 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011686 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011687 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11688 return RETURN_ERR;
11689 }
developer3cc61d12022-09-13 16:36:05 +080011690
11691 params.name = "he_bss_color";
11692 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11693 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011694 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011695 wifi_hostapdWrite(config_file, &params, 1);
11696 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011697 wifi_reloadAp(radio_index);
11698
developer517f3be2023-05-08 10:02:39 +080011699 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11701 return RETURN_OK;
11702}
11703
11704INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11705{
developer3cc61d12022-09-13 16:36:05 +080011706 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011707 char cmd[128] = {0};
11708 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011709
developer3cc61d12022-09-13 16:36:05 +080011710 if (NULL == color)
11711 return RETURN_ERR;
11712
developer2acb9632023-03-14 14:58:31 +080011713 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11714 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011715
developer2acb9632023-03-14 14:58:31 +080011716 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11717 _syscmd(cmd, buf, sizeof(buf));
11718 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011719
developer2acb9632023-03-14 14:58:31 +080011720 return RETURN_OK;
11721}
11722
11723INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11724{
11725 char buf[64] = {0};
11726 char cmd[128] = {0};
11727 char interface_name[16] = {0};
11728 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011729
developer2acb9632023-03-14 14:58:31 +080011730 if (NULL == colorList || NULL == numColorReturned)
11731 return RETURN_ERR;
11732
11733 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11734 return RETURN_ERR;
11735
11736 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11737 _syscmd(cmd, buf, sizeof(buf));
11738 color_bitmap = strtoull(buf, NULL, 16);
11739
11740 *numColorReturned = 0;
11741 for (int i = 0; i < maxNumberColors; i++) {
11742 if (color_bitmap & 1) {
11743 colorList[*numColorReturned] = i;
11744 (*numColorReturned) += 1;
11745 }
11746 color_bitmap >>= 1;
11747 }
developer3cc61d12022-09-13 16:36:05 +080011748 return RETURN_OK;
11749}
11750
developer06a01d92022-09-07 16:32:39 +080011751/* multi-psk support */
11752INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11753{
11754 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011755 char interface_name[16] = {0};
11756
developerac6f1142022-12-20 19:26:35 +080011757 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011758 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011759
developerd946fd62022-12-08 18:03:28 +080011760 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11761 interface_name,
developer06a01d92022-09-07 16:32:39 +080011762 mac[0],
11763 mac[1],
11764 mac[2],
11765 mac[3],
11766 mac[4],
11767 mac[5]
11768 );
11769 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11770 _syscmd(cmd, key->wifi_keyId, 64);
11771
11772
11773 return RETURN_OK;
11774}
11775
11776INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11777{
developerd946fd62022-12-08 18:03:28 +080011778 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011779 FILE *fd = NULL;
11780 char fname[100];
11781 char cmd[128] = {0};
11782 char out[64] = {0};
11783 wifi_key_multi_psk_t * key = NULL;
11784 if(keysNumber < 0)
11785 return RETURN_ERR;
11786
developer431128d2022-12-16 15:30:41 +080011787 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011788 fd = fopen(fname, "w");
11789 if (!fd) {
11790 return RETURN_ERR;
11791 }
11792 key= (wifi_key_multi_psk_t *) keys;
11793 for(int i=0; i<keysNumber; ++i, key++) {
11794 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11795 }
11796 fclose(fd);
11797
11798 //reload file
developerac6f1142022-12-20 19:26:35 +080011799 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011800 return RETURN_ERR;
11801 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011802 _syscmd(cmd, out, 64);
11803 return RETURN_OK;
11804}
11805
11806INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11807{
11808 FILE *fd = NULL;
11809 char fname[100];
11810 char * line = NULL;
11811 char * pos = NULL;
11812 size_t len = 0;
11813 ssize_t read = 0;
11814 INT ret = RETURN_OK;
11815 wifi_key_multi_psk_t *keys_it = NULL;
11816
11817 if (keysNumber < 1) {
11818 return RETURN_ERR;
11819 }
11820
developer431128d2022-12-16 15:30:41 +080011821 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011822 fd = fopen(fname, "r");
11823 if (!fd) {
11824 return RETURN_ERR;
11825 }
11826
11827 if (keys == NULL) {
11828 ret = RETURN_ERR;
11829 goto close;
11830 }
11831
11832 keys_it = keys;
11833 while ((read = getline(&line, &len, fd)) != -1) {
11834 //Strip trailing new line if present
11835 if (read > 0 && line[read-1] == '\n') {
11836 line[read-1] = '\0';
11837 }
11838
11839 if(strcmp(line,"keyid=")) {
11840 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11841 if (!(pos = index(line, ' '))) {
11842 ret = RETURN_ERR;
11843 goto close;
11844 }
11845 pos++;
11846 //Here should be 00:00:00:00:00:00
11847 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11848 printf("Not supported MAC: %s\n", pos);
11849 }
11850 if (!(pos = index(pos, ' '))) {
11851 ret = RETURN_ERR;
11852 goto close;
11853 }
11854 pos++;
11855
11856 //The rest is PSK
11857 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11858 keys_it++;
11859
11860 if(--keysNumber <= 0)
11861 break;
11862 }
11863 }
11864
11865close:
11866 free(line);
11867 fclose(fd);
11868 return ret;
11869}
11870/* end of multi-psk support */
11871
11872INT wifi_setNeighborReports(UINT apIndex,
11873 UINT numNeighborReports,
11874 wifi_NeighborReport_t *neighborReports)
11875{
11876 char cmd[256] = { 0 };
11877 char hex_bssid[13] = { 0 };
11878 char bssid[18] = { 0 };
11879 char nr[256] = { 0 };
11880 char ssid[256];
11881 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011882 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011883 INT ret;
11884
11885 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011886 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011887 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011888 return RETURN_ERR;
11889 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 +080011890 system(cmd);
11891
11892 for(unsigned int i = 0; i < numNeighborReports; i++)
11893 {
11894 memset(ssid, 0, sizeof(ssid));
11895 ret = wifi_getSSIDName(apIndex, ssid);
11896 if (ret != RETURN_OK)
11897 return RETURN_ERR;
11898
11899 memset(hex_ssid, 0, sizeof(hex_ssid));
11900 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11901 sprintf(hex_ssid + k,"%02x", ssid[j]);
11902
11903 snprintf(hex_bssid, sizeof(hex_bssid),
11904 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11905 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11906 snprintf(bssid, sizeof(bssid),
11907 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11908 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11909
11910 snprintf(nr, sizeof(nr),
11911 "%s" // bssid
11912 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11913 "%02hhx" // operclass
11914 "%02hhx" // channel
11915 "%02hhx", // phy_mode
11916 hex_bssid,
11917 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11918 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11919 neighborReports[i].opClass,
11920 neighborReports[i].channel,
11921 neighborReports[i].phyTable);
11922
11923 snprintf(cmd, sizeof(cmd),
11924 "hostapd_cli set_neighbor "
11925 "%s " // bssid
11926 "ssid=%s " // ssid
11927 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011928 "-i %s",
11929 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011930
11931 if (WEXITSTATUS(system(cmd)) != 0)
11932 {
11933 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11934 }
11935 }
11936
11937 return RETURN_OK;
11938}
11939
11940INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11941{
11942 return RETURN_OK;
11943}
11944
11945#ifdef _WIFI_HAL_TEST_
11946int main(int argc,char **argv)
11947{
11948 int index;
11949 INT ret=0;
11950 char buf[1024]="";
11951
11952 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11953 if(argc<3)
11954 {
11955 if(argc==2)
11956 {
11957 if(!strcmp(argv[1], "init"))
11958 return wifi_init();
11959 if(!strcmp(argv[1], "reset"))
11960 return wifi_reset();
11961 if(!strcmp(argv[1], "wifi_getHalVersion"))
11962 {
11963 char buffer[64];
11964 if(wifi_getHalVersion(buffer)==RETURN_OK)
11965 printf("Version: %s\n", buffer);
11966 else
11967 printf("Error in wifi_getHalVersion\n");
11968 return RETURN_OK;
11969 }
11970 }
11971 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11972 exit(-1);
11973 }
11974
11975 index = atoi(argv[2]);
11976 if(strstr(argv[1], "wifi_getApName")!=NULL)
11977 {
11978 wifi_getApName(index,buf);
11979 printf("Ap name is %s \n",buf);
11980 return 0;
11981 }
11982 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11983 {
11984 BOOL b = FALSE;
11985 BOOL *output_bool = &b;
11986 wifi_getRadioAutoChannelEnable(index,output_bool);
11987 printf("Channel enabled = %d \n",b);
11988 return 0;
11989 }
11990 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11991 {
11992 wifi_getApWpaEncryptionMode(index,buf);
11993 printf("encryption enabled = %s\n",buf);
11994 return 0;
11995 }
11996 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11997 {
11998 BOOL b = FALSE;
11999 BOOL *output_bool = &b;
12000 wifi_getApSsidAdvertisementEnable(index,output_bool);
12001 printf("advertisment enabled = %d\n",b);
12002 return 0;
12003 }
12004 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
12005 {
12006 if(argc <= 3 )
12007 {
12008 printf("Insufficient arguments \n");
12009 exit(-1);
12010 }
12011
12012 char sta[20] = {'\0'};
12013 ULLONG handle= 0;
12014 strcpy(sta,argv[3]);
12015 mac_address_t st;
12016 mac_addr_aton(st,sta);
12017
12018 wifi_associated_dev_tid_stats_t tid_stats;
12019 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12020 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12021 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);
12022 }
12023
12024 if(strstr(argv[1], "getApEnable")!=NULL) {
12025 BOOL enable;
12026 ret=wifi_getApEnable(index, &enable);
12027 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12028 }
12029 else if(strstr(argv[1], "setApEnable")!=NULL) {
12030 BOOL enable = atoi(argv[3]);
12031 ret=wifi_setApEnable(index, enable);
12032 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12033 }
12034 else if(strstr(argv[1], "getApStatus")!=NULL) {
12035 char status[64];
12036 ret=wifi_getApStatus(index, status);
12037 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
12038 }
12039 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
12040 {
12041 wifi_getSSIDNameStatus(index,buf);
12042 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
12043 return 0;
12044 }
12045 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
12046 wifi_ssidTrafficStats2_t stats={0};
12047 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
12048 printf("%s %d: returns %d\n", argv[1], index, ret);
12049 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
12050 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
12051 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
12052 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
12053 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
12054 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
12055 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
12056 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
12057 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
12058 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
12059 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
12060 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
12061 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
12062 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
12063 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
12064 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
12065 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
12066 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
12067 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
12068 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
12069 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
12070 }
12071 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
12072 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
12073 UINT array_size=0;
12074 UINT i=0;
12075 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
12076 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12077 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
12078 printf(" neighbor %d:\n", i);
12079 printf(" ap_SSID =%s\n", pt->ap_SSID);
12080 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
12081 printf(" ap_Mode =%s\n", pt->ap_Mode);
12082 printf(" ap_Channel =%d\n", pt->ap_Channel);
12083 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
12084 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12085 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
12086 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
12087 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
12088 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
12089 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12090 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
12091 printf(" ap_Noise =%d\n", pt->ap_Noise);
12092 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
12093 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
12094 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
12095 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
12096 }
12097 if(neighbor_ap_array)
12098 free(neighbor_ap_array); //make sure to free the list
12099 }
12100 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
12101 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
12102 UINT array_size=0;
12103 UINT i=0;
12104 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
12105 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12106 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
12107 printf(" associated_dev %d:\n", i);
12108 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
12109 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
12110 printf(" cli_SNR =%d\n", pt->cli_SNR);
12111 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
12112 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
12113 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
12114 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
12115 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
12116 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
12117 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
12118 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
12119 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
12120 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
12121 }
12122 if(associated_dev_array)
12123 free(associated_dev_array); //make sure to free the list
12124 }
12125
12126 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12127 {
12128#define MAX_ARRAY_SIZE 64
12129 int i, array_size;
12130 char *p, *ch_str;
12131 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12132
12133 if(argc != 5)
12134 {
12135 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12136 exit(-1);
12137 }
12138 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12139
12140 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12141 {
12142 strtok_r(ch_str, ",", &p);
12143 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12144 }
12145 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12146 if(!array_size)
12147 array_size=1;//Need to print current channel statistics
12148 for(i=0; i<array_size; i++)
12149 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12150 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12151 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12152 input_output_channelStats_array[i].ch_number,\
12153 input_output_channelStats_array[i].ch_noise,\
12154 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12155 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12156 input_output_channelStats_array[i].ch_utilization_busy,\
12157 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12158 input_output_channelStats_array[i].ch_utilization_total);
12159 }
12160
12161 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12162 {
12163 if(argc <= 3 )
12164 {
12165 printf("Insufficient arguments \n");
12166 exit(-1);
12167 }
12168 char mac_addr[20] = {'\0'};
12169 wifi_device_t output_struct;
12170 int dev_index = atoi(argv[3]);
12171
12172 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12173 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12174 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);
12175 }
12176
12177 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12178 {
12179 if (argc <= 3)
12180 {
12181 printf("Insufficient arguments\n");
12182 exit(-1);
12183 }
12184 char args[256];
12185 wifi_NeighborReport_t *neighborReports;
12186
12187 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12188 if (!neighborReports)
12189 {
12190 printf("Failed to allocate memory");
12191 exit(-1);
12192 }
12193
12194 for (int i = 3; i < argc; ++i)
12195 {
12196 char *val;
12197 int j = 0;
12198 memset(args, 0, sizeof(args));
12199 strncpy(args, argv[i], sizeof(args));
12200 val = strtok(args, ";");
12201 while (val != NULL)
12202 {
12203 if (j == 0)
12204 {
12205 mac_addr_aton(neighborReports[i - 3].bssid, val);
12206 } else if (j == 1)
12207 {
12208 neighborReports[i - 3].info = strtol(val, NULL, 16);
12209 } else if (j == 2)
12210 {
12211 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12212 } else if (j == 3)
12213 {
12214 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12215 } else if (j == 4)
12216 {
12217 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12218 } else {
12219 printf("Insufficient arguments]n\n");
12220 exit(-1);
12221 }
12222 val = strtok(NULL, ";");
12223 j++;
12224 }
12225 }
12226
12227 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12228 if (ret != RETURN_OK)
12229 {
12230 printf("wifi_setNeighborReports ret = %d", ret);
12231 exit(-1);
12232 }
12233 }
12234 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12235 {
12236 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12237 printf("%s.\n", buf);
12238 else
12239 printf("Error returned\n");
12240 }
12241 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12242 {
12243 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12244 printf("%s.\n", buf);
12245 else
12246 printf("Error returned\n");
12247 }
12248 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12249 {
12250 if (argc <= 2)
12251 {
12252 printf("Insufficient arguments\n");
12253 exit(-1);
12254 }
12255 char buf[64]= {'\0'};
12256 wifi_getRadioOperatingChannelBandwidth(index,buf);
12257 printf("Current bandwidth is %s \n",buf);
12258 return 0;
12259 }
12260 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12261 {
12262 if (argc <= 5)
12263 {
12264 printf("Insufficient arguments\n");
12265 exit(-1);
12266 }
12267 UINT channel = atoi(argv[3]);
12268 UINT width = atoi(argv[4]);
12269 UINT beacon = atoi(argv[5]);
12270 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12271 printf("Result = %d", ret);
12272 }
12273
12274 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12275 return 0;
12276}
12277
12278#endif
12279
12280#ifdef WIFI_HAL_VERSION_3
12281
developer1e5aa162022-09-13 16:06:24 +080012282INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12283{
12284 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12285 if (bitMap & WIFI_BITRATE_1MBPS)
12286 strcat(BasicRate, "1,");
12287 if (bitMap & WIFI_BITRATE_2MBPS)
12288 strcat(BasicRate, "2,");
12289 if (bitMap & WIFI_BITRATE_5_5MBPS)
12290 strcat(BasicRate, "5.5,");
12291 if (bitMap & WIFI_BITRATE_6MBPS)
12292 strcat(BasicRate, "6,");
12293 if (bitMap & WIFI_BITRATE_9MBPS)
12294 strcat(BasicRate, "9,");
12295 if (bitMap & WIFI_BITRATE_11MBPS)
12296 strcat(BasicRate, "11,");
12297 if (bitMap & WIFI_BITRATE_12MBPS)
12298 strcat(BasicRate, "12,");
12299 if (bitMap & WIFI_BITRATE_18MBPS)
12300 strcat(BasicRate, "18,");
12301 if (bitMap & WIFI_BITRATE_24MBPS)
12302 strcat(BasicRate, "24,");
12303 if (bitMap & WIFI_BITRATE_36MBPS)
12304 strcat(BasicRate, "36,");
12305 if (bitMap & WIFI_BITRATE_48MBPS)
12306 strcat(BasicRate, "48,");
12307 if (bitMap & WIFI_BITRATE_54MBPS)
12308 strcat(BasicRate, "54,");
12309 if (strlen(BasicRate) != 0) // remove last comma
12310 BasicRate[strlen(BasicRate) - 1] = '\0';
12311 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12312 return RETURN_OK;
12313}
12314
12315INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12316{
12317 UINT BitMap = 0;
12318 char *rate;
12319
12320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12321 rate = strtok(BasicRatesList, ",");
12322 while(rate != NULL)
12323 {
12324 if (strcmp(rate, "1") == 0)
12325 BitMap |= WIFI_BITRATE_1MBPS;
12326 else if (strcmp(rate, "2") == 0)
12327 BitMap |= WIFI_BITRATE_2MBPS;
12328 else if (strcmp(rate, "5.5") == 0)
12329 BitMap |= WIFI_BITRATE_5_5MBPS;
12330 else if (strcmp(rate, "6") == 0)
12331 BitMap |= WIFI_BITRATE_6MBPS;
12332 else if (strcmp(rate, "9") == 0)
12333 BitMap |= WIFI_BITRATE_9MBPS;
12334 else if (strcmp(rate, "11") == 0)
12335 BitMap |= WIFI_BITRATE_11MBPS;
12336 else if (strcmp(rate, "12") == 0)
12337 BitMap |= WIFI_BITRATE_12MBPS;
12338 else if (strcmp(rate, "18") == 0)
12339 BitMap |= WIFI_BITRATE_18MBPS;
12340 else if (strcmp(rate, "24") == 0)
12341 BitMap |= WIFI_BITRATE_24MBPS;
12342 else if (strcmp(rate, "36") == 0)
12343 BitMap |= WIFI_BITRATE_36MBPS;
12344 else if (strcmp(rate, "48") == 0)
12345 BitMap |= WIFI_BITRATE_48MBPS;
12346 else if (strcmp(rate, "54") == 0)
12347 BitMap |= WIFI_BITRATE_54MBPS;
12348 rate = strtok(NULL, ",");
12349 }
12350 *basicRateBitMap = BitMap;
12351 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12352 return RETURN_OK;
12353}
12354
developer7c4cd202023-03-01 10:56:29 +080012355INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12356{
12357 int center_channel = 0;
12358 char central_channel_str[16] = {0};
12359 char config_file[32] = {0};
12360 struct params param = {0};
12361
12362 center_channel = util_unii_6g_centerfreq("HT320", channel);
12363 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12364 if (channel >= 193)
12365 return RETURN_ERR;
12366 if (channel >= 33) {
12367 if (channel > center_channel)
12368 center_channel += 32;
12369 else
12370 center_channel -= 32;
12371 }
12372 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12373 if (channel <= 29)
12374 return RETURN_ERR;
12375 }
12376 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12377 param.name = "eht_oper_centr_freq_seg0_idx";
12378 param.value = central_channel_str;
12379 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12380 wifi_hostapdWrite(config_file, &param, 1);
12381
12382 return RETURN_OK;
12383}
12384
12385INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12386{
12387 int op_class = 0;
12388 char config_file[32] = {0};
12389 char op_class_str[8] = {0};
12390 struct params param = {0};
12391
12392 if (bandwidth == 20)
12393 op_class = 131;
12394 else if (bandwidth == 40)
12395 op_class = 132;
12396 else if (bandwidth == 80)
12397 op_class = 133;
12398 else if (bandwidth == 160)
12399 op_class = 134;
12400 else if (bandwidth == 320)
12401 op_class = 137;
12402 else
12403 return RETURN_ERR;
12404 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12405 param.name = "op_class";
12406 param.value = op_class_str;
12407 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12408 wifi_hostapdWrite(config_file, &param, 1);
12409 return RETURN_OK;
12410}
12411
12412INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12413{
12414 char config_file[32] = {0};
12415 char buf [16] = {0};
12416
12417 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12418 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12419 return RETURN_ERR; // 6g band should set op_class
12420 *class = (UINT)strtoul(buf, NULL, 10);
12421
12422 return RETURN_OK;
12423}
12424
developer1e5aa162022-09-13 16:06:24 +080012425// 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 +080012426INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12427{
developer1e5aa162022-09-13 16:06:24 +080012428 char buf[128] = {0};
12429 char cmd[128] = {0};
12430 char config_file[64] = {0};
12431 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012432 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012433 wifi_radio_operationParam_t current_param;
12434
12435 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12436
12437 multiple_set = TRUE;
12438 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12439 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12440 return RETURN_ERR;
12441 }
12442 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12443 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12444 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12445 return RETURN_ERR;
12446 }
12447 }
developer5884e982022-10-06 10:52:50 +080012448
12449 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12450 bandwidth = 20;
12451 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12452 bandwidth = 40;
12453 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12454 bandwidth = 80;
12455 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12456 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012457 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12458 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012459 if (operationParam->autoChannelEnabled){
12460 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12461 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12462 return RETURN_ERR;
12463 }
12464 }else{
developer1e5aa162022-09-13 16:06:24 +080012465 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12466 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12467 return RETURN_ERR;
12468 }
12469 }
developer5884e982022-10-06 10:52:50 +080012470
developer7c4cd202023-03-01 10:56:29 +080012471 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12472 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12473 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12474 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12475 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12476 return RETURN_ERR;
12477 }
12478 }
12479
12480 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12481 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12482 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12483 return RETURN_ERR;
12484 }
12485 }
12486
developer1e5aa162022-09-13 16:06:24 +080012487 if (current_param.variant != operationParam->variant) {
12488 // Two different definition bit map, so need to check every bit.
12489 if (operationParam->variant & WIFI_80211_VARIANT_A)
12490 set_mode |= WIFI_MODE_A;
12491 if (operationParam->variant & WIFI_80211_VARIANT_B)
12492 set_mode |= WIFI_MODE_B;
12493 if (operationParam->variant & WIFI_80211_VARIANT_G)
12494 set_mode |= WIFI_MODE_G;
12495 if (operationParam->variant & WIFI_80211_VARIANT_N)
12496 set_mode |= WIFI_MODE_N;
12497 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12498 set_mode |= WIFI_MODE_AC;
12499 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12500 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012501 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12502 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012503 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12504 memset(buf, 0, sizeof(buf));
12505 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12506 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12507 return RETURN_ERR;
12508 }
12509 }
12510 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12511 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12512 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12513 return RETURN_ERR;
12514 }
12515 }
12516 if (current_param.beaconInterval != operationParam->beaconInterval) {
12517 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12518 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12519 return RETURN_ERR;
12520 }
12521 }
12522 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12523 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12524 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12525 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12526 return RETURN_ERR;
12527 }
12528 }
12529 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12530 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12531 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12532 return RETURN_ERR;
12533 }
12534 }
12535 if (current_param.guardInterval != operationParam->guardInterval) {
12536 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12537 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12538 return RETURN_ERR;
12539 }
12540 }
12541 if (current_param.transmitPower != operationParam->transmitPower) {
12542 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12543 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12544 return RETURN_ERR;
12545 }
12546 }
12547 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12548 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12549 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12550 return RETURN_ERR;
12551 }
12552 }
12553 if (current_param.obssCoex != operationParam->obssCoex) {
12554 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12555 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12556 return RETURN_ERR;
12557 }
12558 }
12559 if (current_param.stbcEnable != operationParam->stbcEnable) {
12560 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12561 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12562 return RETURN_ERR;
12563 }
12564 }
developer5735d092023-09-19 20:12:26 +080012565 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12566 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12567 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12568 return RETURN_ERR;
12569 }
12570 }
developer1e5aa162022-09-13 16:06:24 +080012571
12572 // if enable is true, then restart the radio
12573 wifi_setRadioEnable(index, FALSE);
12574 if (operationParam->enable == TRUE)
12575 wifi_setRadioEnable(index, TRUE);
12576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12577
developer06a01d92022-09-07 16:32:39 +080012578 return RETURN_OK;
12579}
12580
12581INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12582{
developer1e5aa162022-09-13 16:06:24 +080012583 char band[64] = {0};
12584 char buf[256] = {0};
12585 char config_file[64] = {0};
12586 char cmd[128] = {0};
12587 int ret = RETURN_ERR;
12588 int mode = 0;
12589 ULONG channel = 0;
12590 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012591
12592 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12593 printf("Entering %s index = %d\n", __func__, (int)index);
12594
developer1e5aa162022-09-13 16:06:24 +080012595 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12596 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12597 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012598 {
developer1e5aa162022-09-13 16:06:24 +080012599 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012600 return RETURN_ERR;
12601 }
12602 operationParam->enable = enabled;
12603
12604 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012605 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012606 {
developer1e5aa162022-09-13 16:06:24 +080012607 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012608 return RETURN_ERR;
12609 }
12610
12611 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012612 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012613 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012614 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012615 else if (!strcmp(band, "6GHz"))
12616 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012617 else
12618 {
developer1e5aa162022-09-13 16:06:24 +080012619 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012620 band);
12621 }
12622
developer1e5aa162022-09-13 16:06:24 +080012623 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12624 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12625 operationParam->channel = 0;
12626 operationParam->autoChannelEnabled = TRUE;
12627 } else {
12628 operationParam->channel = strtol(buf, NULL, 10);
12629 operationParam->autoChannelEnabled = FALSE;
12630 }
12631
developer06a01d92022-09-07 16:32:39 +080012632 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012633 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12634 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12635 return RETURN_ERR;
12636 }
developer06a01d92022-09-07 16:32:39 +080012637 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12638 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12639 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012640 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012641 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12642 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012643 else
12644 {
developer1e5aa162022-09-13 16:06:24 +080012645 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12646 return false;
developer06a01d92022-09-07 16:32:39 +080012647 }
12648
developer7c4cd202023-03-01 10:56:29 +080012649 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12650 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12651 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12652 return RETURN_ERR;
12653 }
12654 }
12655
developer1e5aa162022-09-13 16:06:24 +080012656 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12657 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12658 return RETURN_ERR;
12659 }
12660 // Two different definition bit map, so need to check every bit.
12661 if (mode & WIFI_MODE_A)
12662 operationParam->variant |= WIFI_80211_VARIANT_A;
12663 if (mode & WIFI_MODE_B)
12664 operationParam->variant |= WIFI_80211_VARIANT_B;
12665 if (mode & WIFI_MODE_G)
12666 operationParam->variant |= WIFI_80211_VARIANT_G;
12667 if (mode & WIFI_MODE_N)
12668 operationParam->variant |= WIFI_80211_VARIANT_N;
12669 if (mode & WIFI_MODE_AC)
12670 operationParam->variant |= WIFI_80211_VARIANT_AC;
12671 if (mode & WIFI_MODE_AX)
12672 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012673 if (mode & WIFI_MODE_BE)
12674 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012675 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12676 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12677 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012678 }
developer1e5aa162022-09-13 16:06:24 +080012679 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12680 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12681 return RETURN_ERR;
12682 }
12683 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12684 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12685 return RETURN_ERR;
12686 }
developer06a01d92022-09-07 16:32:39 +080012687
developer1e5aa162022-09-13 16:06:24 +080012688 memset(buf, 0, sizeof(buf));
12689 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12690 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12691 return RETURN_ERR;
12692 }
12693 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12694
12695 memset(buf, 0, sizeof(buf));
12696 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12697 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12698 return RETURN_ERR;
12699 }
12700 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12701
12702 memset(buf, 0, sizeof(buf));
12703 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12704 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12705
12706 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12707 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12708 return RETURN_ERR;
12709 }
12710 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12711 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12712 return RETURN_ERR;
12713 }
12714
12715 memset(buf, 0, sizeof(buf));
12716 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12717 if (strcmp(buf, "-1") == 0) {
12718 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12719 operationParam->ctsProtection = FALSE;
12720 } else {
12721 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12722 operationParam->ctsProtection = TRUE;
12723 }
12724
12725 memset(buf, 0, sizeof(buf));
12726 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12727 if (strcmp(buf, "0") == 0)
12728 operationParam->obssCoex = FALSE;
12729 else
12730 operationParam->obssCoex = TRUE;
12731
12732 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12733 _syscmd(cmd, buf, sizeof(buf));
12734 if (strlen(buf) != 0)
12735 operationParam->stbcEnable = TRUE;
12736 else
12737 operationParam->stbcEnable = FALSE;
12738
developer5735d092023-09-19 20:12:26 +080012739 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12740 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12741 return RETURN_ERR;
12742 }
developer1e5aa162022-09-13 16:06:24 +080012743
12744 // Below value is hardcoded
12745
12746 operationParam->numSecondaryChannels = 0;
12747 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12748 operationParam->channelSecondary[i] = 0;
12749 }
12750 operationParam->csa_beacon_count = 15;
12751 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012752
12753 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12754 return RETURN_OK;
12755}
12756
12757static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12758{
developerc086fb72022-10-04 10:18:22 +080012759 int max_radio_num = 0;
12760
12761 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012762 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012763 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12764 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012765 }
12766
developerc086fb72022-10-04 10:18:22 +080012767 return (arrayIndex * max_radio_num) + radioIndex;
12768}
developer06a01d92022-09-07 16:32:39 +080012769
developerc086fb72022-10-04 10:18:22 +080012770wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12771 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12772 return WIFI_BITRATE_1MBPS;
12773 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12774 return WIFI_BITRATE_2MBPS;
12775 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12776 return WIFI_BITRATE_5_5MBPS;
12777 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12778 return WIFI_BITRATE_6MBPS;
12779 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12780 return WIFI_BITRATE_9MBPS;
12781 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12782 return WIFI_BITRATE_11MBPS;
12783 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12784 return WIFI_BITRATE_12MBPS;
12785 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12786 return WIFI_BITRATE_18MBPS;
12787 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12788 return WIFI_BITRATE_24MBPS;
12789 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12790 return WIFI_BITRATE_36MBPS;
12791 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12792 return WIFI_BITRATE_48MBPS;
12793 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12794 return WIFI_BITRATE_54MBPS;
12795 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012796}
12797
developer1d57d002022-10-12 18:03:15 +080012798INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12799{
12800 if (beacon == WIFI_BITRATE_1MBPS)
12801 strcpy(beacon_str, "1Mbps");
12802 else if (beacon == WIFI_BITRATE_2MBPS)
12803 strcpy(beacon_str, "2Mbps");
12804 else if (beacon == WIFI_BITRATE_5_5MBPS)
12805 strcpy(beacon_str, "5.5Mbps");
12806 else if (beacon == WIFI_BITRATE_6MBPS)
12807 strcpy(beacon_str, "6Mbps");
12808 else if (beacon == WIFI_BITRATE_9MBPS)
12809 strcpy(beacon_str, "9Mbps");
12810 else if (beacon == WIFI_BITRATE_11MBPS)
12811 strcpy(beacon_str, "11Mbps");
12812 else if (beacon == WIFI_BITRATE_12MBPS)
12813 strcpy(beacon_str, "12Mbps");
12814 else if (beacon == WIFI_BITRATE_18MBPS)
12815 strcpy(beacon_str, "18Mbps");
12816 else if (beacon == WIFI_BITRATE_24MBPS)
12817 strcpy(beacon_str, "24Mbps");
12818 else if (beacon == WIFI_BITRATE_36MBPS)
12819 strcpy(beacon_str, "36Mbps");
12820 else if (beacon == WIFI_BITRATE_48MBPS)
12821 strcpy(beacon_str, "48Mbps");
12822 else if (beacon == WIFI_BITRATE_54MBPS)
12823 strcpy(beacon_str, "54Mbps");
12824 return RETURN_OK;
12825}
12826
developer74ed4192023-09-21 17:15:17 +080012827void checkVapStatus(int apIndex, bool *enable)
12828{
12829 char if_name[16] = {0};
12830 char cmd[128] = {0};
12831 char buf[128] = {0};
12832
12833 *enable = FALSE;
12834 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12835 return;
12836
12837 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12838 _syscmd(cmd, buf, sizeof(buf));
12839 if (strlen(buf) > 0)
12840 *enable = TRUE;
12841 return;
12842}
12843
developerefb790a2023-12-26 18:58:32 +080012844INT wifi_getVapInfoMisc(int vap_index)
12845{
12846 char config_file[MAX_BUF_SIZE] = {0};
12847
12848 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX,vap_index);
12849 wifi_hostapdRead(config_file,"ssid",vap_info[vap_index].ssid, MAX_BUF_SIZE);
12850 wifi_hostapdRead(config_file,"wpa", vap_info[vap_index].wpa, MAX_BUF_SIZE);
12851 wifi_hostapdRead(config_file,"wpa_key_mgmt", vap_info[vap_index].wpa_key_mgmt, MAX_BUF_SIZE);
12852 wifi_hostapdRead(config_file,"wpa_passphrase", vap_info[vap_index].wpa_passphrase, MAX_BUF_SIZE);
12853 wifi_hostapdRead(config_file,"ap_isolate", vap_info[vap_index].ap_isolate, MAX_BUF_SIZE);
12854 wifi_hostapdRead(config_file,"macaddr_acl", vap_info[vap_index].macaddr_acl, MAX_BUF_SIZE);
12855 wifi_hostapdRead(config_file,"bss_transition", vap_info[vap_index].bss_transition, MAX_BUF_SIZE);
12856 wifi_hostapdRead(config_file,"ignore_broadcast_ssid", vap_info[vap_index].ignore_broadcast_ssid, MAX_BUF_SIZE);
12857 wifi_hostapdRead(config_file, "max_num_sta", vap_info[vap_index].max_sta, MAX_BUF_SIZE);
12858 return RETURN_OK;
12859}
12860
12861int wifi_Syncthread(void *arg)
12862{
12863 int radio_idx = 0, i = 0;
12864 int vap_index = 0;
developera2af46a2024-01-04 19:11:23 +080012865 int max_radio = 0;
developerefb790a2023-12-26 18:58:32 +080012866
developera2af46a2024-01-04 19:11:23 +080012867 wifi_getMaxRadioNumber(&max_radio);
developerefb790a2023-12-26 18:58:32 +080012868 while (1)
12869 {
12870 sleep(5);
developera2af46a2024-01-04 19:11:23 +080012871 for (radio_idx = 0; radio_idx < max_radio; radio_idx++)
developerefb790a2023-12-26 18:58:32 +080012872 {
12873 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
12874 {
12875 vap_index = array_index_to_vap_index(radio_idx, i);
12876 if (vap_index >= 0)
12877 wifi_getVapInfoMisc(vap_index);
12878 }
12879 }
12880 syn_flag = 1;
12881 }
12882 return 0;
12883}
12884
developer06a01d92022-09-07 16:32:39 +080012885INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12886{
developerc086fb72022-10-04 10:18:22 +080012887 INT mode = 0;
12888 INT ret = -1;
12889 INT output = 0;
12890 int i = 0;
12891 int vap_index = 0;
12892 BOOL enabled = FALSE;
12893 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012894 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012895
developer06a01d92022-09-07 16:32:39 +080012896
12897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12898 printf("Entering %s index = %d\n", __func__, (int)index);
12899
developera77d84b2023-02-22 16:10:50 +080012900 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012901 {
developerc086fb72022-10-04 10:18:22 +080012902 map->vap_array[i].radio_index = index;
12903
developer06a01d92022-09-07 16:32:39 +080012904 vap_index = array_index_to_vap_index(index, i);
12905 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012906 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012907
developerc086fb72022-10-04 10:18:22 +080012908 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012909
12910 map->vap_array[i].vap_index = vap_index;
12911
12912 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012913 ret = wifi_getApName(vap_index, buf);
12914 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012915 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12916
developerc086fb72022-10-04 10:18:22 +080012917 return RETURN_ERR;
12918 }
12919 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12920
12921 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012922 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012923 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012924 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012925 return RETURN_ERR;
12926 }
12927 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 +080012928
developer74ed4192023-09-21 17:15:17 +080012929 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012930 map->vap_array[i].u.bss_info.enabled = enabled;
12931
developerc086fb72022-10-04 10:18:22 +080012932 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12933 if (ret != RETURN_OK) {
12934 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12935 return RETURN_ERR;
12936 }
developer06a01d92022-09-07 16:32:39 +080012937 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012938
12939 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12940 if (ret != RETURN_OK) {
12941 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12942 return RETURN_ERR;
12943 }
12944 map->vap_array[i].u.bss_info.isolation = enabled;
12945
12946 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12947 if (ret != RETURN_OK) {
12948 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12949 return RETURN_ERR;
12950 }
12951 map->vap_array[i].u.bss_info.bssMaxSta = output;
12952
12953 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12954 if (ret != RETURN_OK) {
12955 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12956 return RETURN_ERR;
12957 }
12958 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012959
developerc086fb72022-10-04 10:18:22 +080012960 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12961 if (ret != RETURN_OK) {
12962 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12963 return RETURN_ERR;
12964 }
12965 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012966
developerc086fb72022-10-04 10:18:22 +080012967 ret = wifi_getApSecurity(vap_index, &security);
12968 if (ret != RETURN_OK) {
12969 printf("%s: wifi_getApSecurity return error\n", __func__);
12970 return RETURN_ERR;
12971 }
12972 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012973
developerc086fb72022-10-04 10:18:22 +080012974 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12975 if (ret != RETURN_OK) {
12976 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12977 return RETURN_ERR;
12978 }
12979 if (mode == 0)
12980 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12981 else
12982 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12983 if (mode == 1)
12984 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12985 else if (mode == 2)
12986 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012987
developerc086fb72022-10-04 10:18:22 +080012988 ret = wifi_getApWmmEnable(vap_index, &enabled);
12989 if (ret != RETURN_OK) {
12990 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12991 return RETURN_ERR;
12992 }
12993 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012994
developerc086fb72022-10-04 10:18:22 +080012995 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12996 if (ret != RETURN_OK) {
12997 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012998 return RETURN_ERR;
12999 }
developerc086fb72022-10-04 10:18:22 +080013000 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080013001
13002 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080013003 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080013004 if (ret != RETURN_OK) {
13005 printf("%s: wifi_getApBeaconRate return error\n", __func__);
13006 return RETURN_ERR;
13007 }
13008 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080013009
developerc086fb72022-10-04 10:18:22 +080013010 memset(buf, 0, sizeof(buf));
13011 ret = wifi_getBaseBSSID(vap_index, buf);
13012 if (ret != RETURN_OK) {
13013 printf("%s: wifi_getBaseBSSID return error\n", __func__);
13014 return RETURN_ERR;
13015 }
13016 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13017 &map->vap_array[i].u.bss_info.bssid[0],
13018 &map->vap_array[i].u.bss_info.bssid[1],
13019 &map->vap_array[i].u.bss_info.bssid[2],
13020 &map->vap_array[i].u.bss_info.bssid[3],
13021 &map->vap_array[i].u.bss_info.bssid[4],
13022 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080013023 // 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]);
13024
13025 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
13026 if (ret != RETURN_OK) {
13027 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
13028 return RETURN_ERR;
13029 }
13030 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080013031
13032 ret = wifi_getApWpsEnable(vap_index, &enabled);
13033 if (ret != RETURN_OK) {
13034 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
13035 return RETURN_ERR;
13036 }
13037
13038 map->vap_array[i].u.bss_info.wps.enable = enabled;
13039
developera77d84b2023-02-22 16:10:50 +080013040 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080013041 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080013042 }
developerefb790a2023-12-26 18:58:32 +080013043
13044 if (!tflag) {
13045 result = pthread_create(&pthread_id, NULL, wifi_Syncthread,NULL);
13046 if (result != 0)
13047 printf("%s %d fail create sync thread\n", __func__, __LINE__);
13048 else
13049 tflag = 1;
13050 }
13051
developer06a01d92022-09-07 16:32:39 +080013052 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13053 return RETURN_OK;
13054}
13055
developer431128d2022-12-16 15:30:41 +080013056
developerd946fd62022-12-08 18:03:28 +080013057static int prepareInterface(UINT apIndex, char *new_interface)
13058{
13059 char cur_interface[16] = {0};
13060 char config_file[128] = {0};
13061 char cmd[128] = {0};
13062 char buf[16] = {0};
13063 int max_radio_num = 0;
13064 int radioIndex = -1;
13065 int phyIndex = -1;
13066
13067 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13068 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13069
13070 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
13071 wifi_getMaxRadioNumber(&max_radio_num);
13072 radioIndex = apIndex % max_radio_num;
13073 phyIndex = radio_index_to_phy(radioIndex);
13074 // disable and del old interface, then add new interface
13075 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080013076 if (!(apIndex/max_radio_num)) {
13077 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
13078 _syscmd(cmd, buf, sizeof(buf));
13079 }
developerd946fd62022-12-08 18:03:28 +080013080 }
developer431128d2022-12-16 15:30:41 +080013081 // update the vap status file
13082 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13083 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080013084 return RETURN_OK;
13085}
13086
developer06a01d92022-09-07 16:32:39 +080013087INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13088{
developerd946fd62022-12-08 18:03:28 +080013089 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013090 unsigned int i;
13091 wifi_vap_info_t *vap_info = NULL;
13092 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080013093 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080013094 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080013095 char buf[256] = {0};
13096 char cmd[128] = {0};
13097 char config_file[64] = {0};
13098 char bssid[32] = {0};
13099 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080013100 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080013101
13102 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13103 printf("Entering %s index = %d\n", __func__, (int)index);
13104 for (i = 0; i < map->num_vaps; i++)
13105 {
developer1d57d002022-10-12 18:03:15 +080013106 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080013107 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080013108
13109 // Check vap status file to enable multiple ap if the system boot.
13110 checkVapStatus(vap_info->vap_index, &enable);
13111 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080013112 continue;
developer06a01d92022-09-07 16:32:39 +080013113
developer1d57d002022-10-12 18:03:15 +080013114 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13115
developer431128d2022-12-16 15:30:41 +080013116 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13117 enable = FALSE;
13118
13119 // multi-ap first up need to copy current radio config
13120 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080013121 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13122 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080013123 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13124 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13125 } else {
13126 // Check whether the interface name is valid or this ap change it.
13127 int apIndex = -1;
13128 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13129 if (apIndex != -1 && apIndex != vap_info->vap_index)
13130 continue;
13131 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080013132 }
developer06a01d92022-09-07 16:32:39 +080013133
developer1d57d002022-10-12 18:03:15 +080013134 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080013135 params[0].name = "interface";
13136 params[0].value = vap_info->vap_name;
13137 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13138 params[1].name = "bssid";
13139 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080013140 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080013141 params[2].name = "wpa_psk_file";
13142 params[2].value = psk_file;
13143
13144 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13145 wifi_hostapdWrite(config_file, params, 3);
13146
13147 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13148 _syscmd(cmd, buf, sizeof(buf));
13149
13150 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13151 if (ret != RETURN_OK) {
13152 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13153 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013154 }
developer1d57d002022-10-12 18:03:15 +080013155
13156 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13157 if (ret != RETURN_OK) {
13158 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13159 return RETURN_ERR;
13160 }
13161
13162 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13163 if (ret != RETURN_OK) {
13164 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13165 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013166 }
13167
developer1d57d002022-10-12 18:03:15 +080013168 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13169 if (ret != RETURN_OK) {
13170 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13171 return RETURN_ERR;
13172 }
developer06a01d92022-09-07 16:32:39 +080013173
developer1d57d002022-10-12 18:03:15 +080013174 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13175 if (ret != RETURN_OK) {
13176 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13177 return RETURN_ERR;
13178 }
developer06a01d92022-09-07 16:32:39 +080013179
developer1d57d002022-10-12 18:03:15 +080013180 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13181 if (ret != RETURN_OK) {
13182 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13183 return RETURN_ERR;
13184 }
13185
developer804c64f2022-10-19 13:54:40 +080013186 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080013187 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080013188 }else {
13189 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080013190 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080013191 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13192 _syscmd(cmd, buf, sizeof(buf));
13193 }else{
developer1d57d002022-10-12 18:03:15 +080013194 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080013195 }
developer1d57d002022-10-12 18:03:15 +080013196 }
13197
13198 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13199 if (ret != RETURN_OK) {
13200 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13201 return RETURN_ERR;
13202 }
13203
13204 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13205 if (ret != RETURN_OK) {
13206 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13207 return RETURN_ERR;
13208 }
13209
13210 memset(buf, 0, sizeof(buf));
13211 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13212 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
13213 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13214 if (ret != RETURN_OK) {
13215 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13216 return RETURN_ERR;
13217 }
13218
developer1d57d002022-10-12 18:03:15 +080013219 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13220 if (ret != RETURN_OK) {
13221 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13222 return RETURN_ERR;
13223 }
13224
13225 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13226 if (ret != RETURN_OK) {
13227 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13228 return RETURN_ERR;
13229 }
developer06a01d92022-09-07 16:32:39 +080013230
developer894affa2023-05-10 18:13:19 +080013231 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
13232 if (ret != RETURN_OK) {
13233 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
13234 return RETURN_ERR;
13235 }
13236
developer2f995fb2023-02-24 10:40:44 +080013237 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080013238 if (vap_info->u.bss_info.enabled == TRUE)
13239 wifi_setApEnable(vap_info->vap_index, TRUE);
13240
developer2f995fb2023-02-24 10:40:44 +080013241 multiple_set = FALSE;
13242
13243 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080013244 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080013245 // The set wps methods function should check whether wps is configured.
13246 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
13247 if (ret != RETURN_OK) {
13248 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
13249 return RETURN_ERR;
13250 }
13251 // wifi_setApWpsConfigMethodsEnabled only write to config.
13252 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13253 if (ret != RETURN_OK) {
13254 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13255 return RETURN_ERR;
13256 }
13257 }
developer2f995fb2023-02-24 10:40:44 +080013258
developer894affa2023-05-10 18:13:19 +080013259 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013260 }
developerfb09ba62023-06-09 17:03:21 +080013261
13262 // IGMP Snooping enable should be placed after all hostapd_reload.
13263 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13264 if (ret != RETURN_OK) {
13265 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13266 return RETURN_ERR;
13267 }
13268
developer06a01d92022-09-07 16:32:39 +080013269 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13270 return RETURN_OK;
13271}
13272
13273int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13274{
13275 char *token, *next;
13276 const char s[2] = ",";
13277 int count =0;
13278
13279 /* get the first token */
13280 token = strtok_r(pchannels, s, &next);
13281
13282 /* walk through other tokens */
13283 while( token != NULL && count < MAX_CHANNELS) {
13284 chlistptr->channels_list[count++] = atoi(token);
13285 token = strtok_r(NULL, s, &next);
13286 }
13287
13288 return count;
13289}
13290
13291static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13292{
13293 INT status;
13294 wifi_channels_list_t *chlistp;
13295 CHAR output_string[64];
13296 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013297 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013298 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013299
13300 if(rcap == NULL)
13301 {
13302 return RETURN_ERR;
13303 }
13304
13305 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013306 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013307
developer1e5aa162022-09-13 16:06:24 +080013308 if (band == band_2_4)
13309 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13310 else if (band == band_5)
13311 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13312 else if (band == band_6)
13313 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013314
13315 chlistp = &(rcap->channel_list[0]);
13316 memset(pchannels, 0, sizeof(pchannels));
13317
13318 /* possible number of radio channels */
13319 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13320 {
13321 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13322 }
13323 /* Number of channels and list*/
13324 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13325
13326 /* autoChannelSupported */
13327 /* always ON with wifi_getRadioAutoChannelSupported */
13328 rcap->autoChannelSupported = TRUE;
13329
13330 /* DCSSupported */
13331 /* always ON with wifi_getRadioDCSSupported */
13332 rcap->DCSSupported = TRUE;
13333
13334 /* zeroDFSSupported - TBD */
13335 rcap->zeroDFSSupported = FALSE;
13336
13337 /* Supported Country List*/
13338 memset(output_string, 0, sizeof(output_string));
13339 status = wifi_getRadioCountryCode(radioIndex, output_string);
13340 if( status != 0 ) {
13341 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13342 return RETURN_ERR;
13343 } else {
13344 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13345 }
13346 if(!strcmp(output_string,"US")){
13347 rcap->countrySupported[0] = wifi_countrycode_US;
13348 rcap->countrySupported[1] = wifi_countrycode_CA;
13349 } else if (!strcmp(output_string,"CA")) {
13350 rcap->countrySupported[0] = wifi_countrycode_CA;
13351 rcap->countrySupported[1] = wifi_countrycode_US;
13352 } else {
13353 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13354 }
13355
13356 rcap->numcountrySupported = 2;
13357
13358 /* csi */
13359 rcap->csi.maxDevices = 8;
13360 rcap->csi.soudingFrameSupported = TRUE;
13361
developer7930d352022-12-21 17:55:42 +080013362 wifi_GetInterfaceName(radioIndex, interface_name);
13363 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013364
13365 /* channelWidth - all supported bandwidths */
13366 int i=0;
13367 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013368
13369 /* mode - all supported variants */
13370 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13371 wifi_getRadioSupportedStandards(radioIndex, output_string);
13372
developer06a01d92022-09-07 16:32:39 +080013373 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13374 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13375 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013376 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013377
developer7c4cd202023-03-01 10:56:29 +080013378 if (strstr(output_string, "n") != NULL)
13379 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13380 if (strstr(output_string, "ax") != NULL)
13381 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13382 if (strstr(output_string, "be") != NULL)
13383 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13384 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013385 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13386 WIFI_CHANNELBANDWIDTH_40MHZ |
13387 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013388 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013389
developer7c4cd202023-03-01 10:56:29 +080013390 if (strstr(output_string, "n") != NULL)
13391 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13392 if (strstr(output_string, "ac") != NULL)
13393 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13394 if (strstr(output_string, "ax") != NULL)
13395 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13396 if (strstr(output_string, "be") != NULL)
13397 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13398 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13399 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13400 WIFI_CHANNELBANDWIDTH_40MHZ |
13401 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013402 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013403
13404 if (strstr(output_string, "be") != NULL) {
13405 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13406 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13407 }
developer06a01d92022-09-07 16:32:39 +080013408 }
developer7c4cd202023-03-01 10:56:29 +080013409
developer06a01d92022-09-07 16:32:39 +080013410 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13411 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13412
13413 /* supportedBitRate - all supported bitrates */
13414 rcap->supportedBitRate[i] = 0;
13415 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13416 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13417 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13418 }
developer1e5aa162022-09-13 16:06:24 +080013419 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013420 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13421 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13422 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13423 }
13424
13425
13426 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13427 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13428 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13429 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13430 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13431 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13432 rcap->cipherSupported = 0;
13433 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13434 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13435
13436 return RETURN_OK;
13437}
13438
13439INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13440{
developer30423732022-12-01 16:17:49 +080013441 INT status = 0, radioIndex = 0;
13442 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013443 int iter = 0;
developer30423732022-12-01 16:17:49 +080013444 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013445 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013446 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013447
13448 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13449
13450 memset(cap, 0, sizeof(wifi_hal_capability_t));
13451
13452 /* version */
13453 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13454 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13455
13456 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013457 wifi_getMaxRadioNumber(&max_num_radios);
13458 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013459
13460 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13461 {
13462 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13463 if (status != 0) {
13464 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13465 return RETURN_ERR;
13466 }
13467
13468 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13469 {
developer804c64f2022-10-19 13:54:40 +080013470 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013471 {
13472 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13473 return RETURN_ERR;
13474 }
13475 iface_info = &cap->wifi_prop.interface_map[iter];
13476 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13477 iface_info->rdk_radio_index = radioIndex;
13478 memset(output, 0, sizeof(output));
13479 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13480 {
13481 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13482 }
13483 // TODO: bridge name
13484 // TODO: vlan id
13485 // TODO: primary
13486 iface_info->index = array_index_to_vap_index(radioIndex, j);
13487 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013488 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013489 {
13490 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13491 }
13492 iter++;
13493 }
13494 }
13495
13496 cap->BandSteeringSupported = FALSE;
13497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13498 return RETURN_OK;
13499}
13500
developer9df4e652022-10-11 11:27:38 +080013501INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13502{
13503 struct params h_config={0};
13504 char config_file[64] = {0};
13505
13506 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13507
13508 h_config.name = "okc";
13509 h_config.value = okc_enable?"1":"0";
13510
13511 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13512 wifi_hostapdWrite(config_file, &h_config, 1);
13513 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13514
13515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13516 return RETURN_OK;
13517}
13518
13519INT wifi_setSAEMFP(int ap_index, BOOL enable)
13520{
13521 struct params h_config={0};
13522 char config_file[64] = {0};
13523 char buf[128] = {0};
13524
13525 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13526
13527 h_config.name = "sae_require_mfp";
13528 h_config.value = enable?"1":"0";
13529
13530 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13531 wifi_hostapdWrite(config_file, &h_config, 1);
13532 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13533
13534 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13535 return RETURN_OK;
13536}
13537
13538INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13539{
13540 struct params h_config={0};
13541 char config_file[64] = {0};
13542 char buf[128] = {0};
13543
13544 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13545
13546 h_config.name = "sae_pwe";
13547 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13548 h_config.value = buf;
13549
13550 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13551 wifi_hostapdWrite(config_file, &h_config, 1);
13552 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13553
13554 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13555 return RETURN_OK;
13556}
13557
13558INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13559{
13560 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13561 struct params h_config={0};
13562 char config_file[64] = {0};
13563
13564 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13565
13566 h_config.name = "wpa_disable_eapol_key_retries";
13567 h_config.value = disable_EAPOL_retries?"1":"0";
13568
13569 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13570 wifi_hostapdWrite(config_file, &h_config, 1);
13571 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13572
13573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13574 return RETURN_OK;
13575}
13576
developer06a01d92022-09-07 16:32:39 +080013577INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13578{
developer587c1b62022-09-27 15:58:59 +080013579 char buf[128] = {0};
13580 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013581 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013582 char password[64] = {0};
13583 char mfp[32] = {0};
13584 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013585 BOOL okc_enable = FALSE;
13586 BOOL sae_MFP = FALSE;
13587 BOOL disable_EAPOL_retries = TRUE;
13588 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013589 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013590 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013591
13592 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13593
13594 multiple_set = TRUE;
13595 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13596 if (security->mode == wifi_security_mode_none) {
13597 strcpy(wpa_mode, "None");
13598 } else if (security->mode == wifi_security_mode_wpa_personal)
13599 strcpy(wpa_mode, "WPA-Personal");
13600 else if (security->mode == wifi_security_mode_wpa2_personal)
13601 strcpy(wpa_mode, "WPA2-Personal");
13602 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13603 strcpy(wpa_mode, "WPA-WPA2-Personal");
13604 else if (security->mode == wifi_security_mode_wpa_enterprise)
13605 strcpy(wpa_mode, "WPA-Enterprise");
13606 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13607 strcpy(wpa_mode, "WPA2-Enterprise");
13608 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13609 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013610 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013611 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013612 okc_enable = TRUE;
13613 sae_MFP = TRUE;
13614 sae_pwe = 2;
13615 disable_EAPOL_retries = FALSE;
13616 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013617 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013618 okc_enable = TRUE;
13619 sae_MFP = TRUE;
13620 sae_pwe = 2;
13621 disable_EAPOL_retries = FALSE;
13622 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013623 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013624 sae_MFP = TRUE;
13625 sae_pwe = 2;
13626 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013627 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013628 strcpy(wpa_mode, "OWE");
13629 sae_MFP = TRUE;
13630 sae_pwe = 2;
13631 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013632 }
13633
13634 band = wifi_index_to_band(ap_index);
13635 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13636 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13637 return RETURN_ERR;
13638 }
developer587c1b62022-09-27 15:58:59 +080013639
13640 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013641 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013642 wifi_setSAEMFP(ap_index, sae_MFP);
13643 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013644 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013645
developerae432c62023-04-24 11:07:20 +080013646 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013647 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) {
13648 int key_len = strlen(security->u.key.key);
13649 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13650 if (key_len == 64) { // set wpa_psk
13651 strncpy(password, security->u.key.key, 64); // 64 characters
13652 password[64] = '\0';
13653 wifi_setApSecurityPreSharedKey(ap_index, password);
13654 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13655 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13656 strncpy(password, security->u.key.key, 63);
13657 password[63] = '\0';
13658 wifi_setApSecurityKeyPassphrase(ap_index, password);
13659 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13660 } else
13661 return RETURN_ERR;
13662 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013663 }
13664 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13665 params.name = "sae_password";
13666 params.value = security->u.key.key;
13667 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013668 } else { // remove sae_password
13669 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13670 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013671 }
13672 }
developer587c1b62022-09-27 15:58:59 +080013673
13674 if (security->mode != wifi_security_mode_none) {
13675 memset(&params, 0, sizeof(params));
13676 params.name = "wpa_pairwise";
13677 if (security->encr == wifi_encryption_tkip)
13678 params.value = "TKIP";
13679 else if (security->encr == wifi_encryption_aes)
13680 params.value = "CCMP";
13681 else if (security->encr == wifi_encryption_aes_tkip)
13682 params.value = "TKIP CCMP";
13683 wifi_hostapdWrite(config_file, &params, 1);
13684 }
13685
13686 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013687 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013688 else if (security->mfp == wifi_mfp_cfg_optional)
13689 strcpy(mfp, "Optional");
13690 else if (security->mfp == wifi_mfp_cfg_required)
13691 strcpy(mfp, "Required");
13692 wifi_setApSecurityMFPConfig(ap_index, mfp);
13693
13694 memset(&params, 0, sizeof(params));
13695 params.name = "transition_disable";
13696 if (security->wpa3_transition_disable == TRUE)
13697 params.value = "0x01";
13698 else
13699 params.value = "0x00";
13700 wifi_hostapdWrite(config_file, &params, 1);
13701
13702 memset(&params, 0, sizeof(params));
13703 params.name = "wpa_group_rekey";
13704 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13705 params.value = buf;
13706 wifi_hostapdWrite(config_file, &params, 1);
13707
13708 memset(&params, 0, sizeof(params));
13709 params.name = "wpa_strict_rekey";
13710 params.value = security->strict_rekey?"1":"0";
13711 wifi_hostapdWrite(config_file, &params, 1);
13712
13713 memset(&params, 0, sizeof(params));
13714 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013715 if (security->eapol_key_retries == 0)
13716 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013717 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13718 params.value = buf;
13719 wifi_hostapdWrite(config_file, &params, 1);
13720
13721 memset(&params, 0, sizeof(params));
13722 params.name = "disable_pmksa_caching";
13723 params.value = security->disable_pmksa_caching?"1":"0";
13724 wifi_hostapdWrite(config_file, &params, 1);
13725
developer23e71282023-01-18 10:25:19 +080013726 if (multiple_set == FALSE) {
13727 wifi_setApEnable(ap_index, FALSE);
13728 wifi_setApEnable(ap_index, TRUE);
13729 }
developer587c1b62022-09-27 15:58:59 +080013730
13731 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13732
developer06a01d92022-09-07 16:32:39 +080013733 return RETURN_OK;
13734}
13735
13736INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13737{
developer9df4e652022-10-11 11:27:38 +080013738 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013739 char config_file[128] = {0};
13740 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013741 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013742
13743 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13744 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13745 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13746 security->mode = wifi_security_mode_none;
13747 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013748 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013749 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013750 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013751 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013752 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013753 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013754 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013755 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013756 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013757 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013758 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013759 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013760 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013761 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013762 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013763 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013764 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013765 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013766 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013767 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013768 }
13769
13770 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13771 if (security->mode == wifi_security_mode_none)
13772 security->encr = wifi_encryption_none;
13773 else {
13774 if (strcmp(buf, "TKIP") == 0)
13775 security->encr = wifi_encryption_tkip;
13776 else if (strcmp(buf, "CCMP") == 0)
13777 security->encr = wifi_encryption_aes;
13778 else
13779 security->encr = wifi_encryption_aes_tkip;
13780 }
13781
developer9df4e652022-10-11 11:27:38 +080013782 if (security->mode != wifi_encryption_none) {
13783 memset(buf, 0, sizeof(buf));
13784 // wpa3 can use one or both configs as password, so we check sae_password first.
13785 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013786 if (strlen(buf) != 0) {
13787 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13788 security->u.key.type = wifi_security_key_type_sae;
13789 set_sae = TRUE;
13790 strncpy(security->u.key.key, buf, sizeof(buf));
13791 }
13792 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13793 if (strlen(buf) != 0){
13794 if (set_sae == TRUE)
13795 security->u.key.type = wifi_security_key_type_psk_sae;
13796 else if (strlen(buf) == 64)
13797 security->u.key.type = wifi_security_key_type_psk;
13798 else
13799 security->u.key.type = wifi_security_key_type_pass;
13800 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013801 }
developer9df4e652022-10-11 11:27:38 +080013802 security->u.key.key[255] = '\0';
13803 }
13804
developer587c1b62022-09-27 15:58:59 +080013805 memset(buf, 0, sizeof(buf));
13806 wifi_getApSecurityMFPConfig(ap_index, buf);
13807 if (strcmp(buf, "Disabled") == 0)
13808 security->mfp = wifi_mfp_cfg_disabled;
13809 else if (strcmp(buf, "Optional") == 0)
13810 security->mfp = wifi_mfp_cfg_optional;
13811 else if (strcmp(buf, "Required") == 0)
13812 security->mfp = wifi_mfp_cfg_required;
13813
13814 memset(buf, 0, sizeof(buf));
13815 security->wpa3_transition_disable = FALSE;
13816 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13817 disable = strtol(buf, NULL, 16);
13818 if (disable != 0)
13819 security->wpa3_transition_disable = TRUE;
13820
13821 memset(buf, 0, sizeof(buf));
13822 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13823 if (strlen(buf) == 0)
13824 security->rekey_interval = 86400;
13825 else
13826 security->rekey_interval = strtol(buf, NULL, 10);
13827
13828 memset(buf, 0, sizeof(buf));
13829 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13830 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013831 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013832 else
13833 security->strict_rekey = strtol(buf, NULL, 10);
13834
13835 memset(buf, 0, sizeof(buf));
13836 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13837 if (strlen(buf) == 0)
13838 security->eapol_key_retries = 4;
13839 else
13840 security->eapol_key_retries = strtol(buf, NULL, 10);
13841
13842 memset(buf, 0, sizeof(buf));
13843 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13844 if (strlen(buf) == 0)
13845 security->disable_pmksa_caching = FALSE;
13846 else
13847 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13848
13849 /* TODO
13850 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13851 */
13852 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13853 security->eap_identity_req_timeout = 0;
13854 security->eap_identity_req_retries = 0;
13855 security->eap_req_timeout = 0;
13856 security->eap_req_retries = 0;
13857 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013858 return RETURN_OK;
13859}
13860
13861#endif /* WIFI_HAL_VERSION_3 */
13862
13863#ifdef WIFI_HAL_VERSION_3_PHASE2
13864INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13865{
developerd946fd62022-12-08 18:03:28 +080013866 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013867 char cmd[128] = {0};
13868 char buf[128] = {0};
13869 char *mac_addr = NULL;
13870 BOOL status = FALSE;
13871 size_t len = 0;
13872
13873 if(ap_index > MAX_APS)
13874 return RETURN_ERR;
13875
13876 *output_numDevices = 0;
13877 wifi_getApEnable(ap_index, &status);
13878 if (status == FALSE)
13879 return RETURN_OK;
13880
developerac6f1142022-12-20 19:26:35 +080013881 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013882 return RETURN_ERR;
13883 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013884 _syscmd(cmd, buf, sizeof(buf));
13885
13886 mac_addr = strtok(buf, "\n");
13887 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13888 *output_numDevices = i + 1;
13889 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13890 addr_ptr = output_deviceMacAddressArray[i];
13891 mac_addr_aton(addr_ptr, mac_addr);
13892 mac_addr = strtok(NULL, "\n");
13893 }
13894
13895 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013896}
13897#else
13898INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13899{
developerd946fd62022-12-08 18:03:28 +080013900 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013901 char cmd[128];
13902 BOOL status = false;
13903
13904 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13905 return RETURN_ERR;
13906
13907 output_buf[0] = '\0';
13908
13909 wifi_getApEnable(ap_index,&status);
13910 if (!status)
13911 return RETURN_OK;
13912
developerac6f1142022-12-20 19:26:35 +080013913 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013914 return RETURN_ERR;
13915 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013916 _syscmd(cmd, output_buf, output_buf_size);
13917
13918 return RETURN_OK;
13919}
13920#endif
developer2f513ab2022-09-13 14:26:06 +080013921
13922INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13923{
13924 char output[16]={'\0'};
13925 char config_file[MAX_BUF_SIZE] = {0};
13926
13927 if (!enable)
13928 return RETURN_ERR;
13929
13930 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13931 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13932
13933 if (strlen(output) == 0)
13934 *enable = FALSE;
13935 else if (strncmp(output, "1", 1) == 0)
13936 *enable = TRUE;
13937 else
13938 *enable = FALSE;
13939
13940 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13941 return RETURN_OK;
13942}
developer2d9c30f2022-09-13 15:06:14 +080013943
13944INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13945{
developer804c64f2022-10-19 13:54:40 +080013946 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013947 return RETURN_ERR;
13948 *output_enable=TRUE;
13949 return RETURN_OK;
13950}
developerfd7d2892022-09-13 16:44:53 +080013951
13952INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13953{
13954 char cmd[128] = {0};
13955 char buf[128] = {0};
13956 char line[128] = {0};
13957 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013958 FILE *f = NULL;
13959 int index = 0;
13960 int exp = 0;
13961 int mantissa = 0;
13962 int duration = 0;
13963 int radio_index = 0;
13964 int max_radio_num = 0;
13965 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013966 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13968
13969 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013970
developerfd7d2892022-09-13 16:44:53 +080013971 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013972
13973 phyId = radio_index_to_phy(radio_index);
13974 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013975 _syscmd(cmd, buf, sizeof(buf));
13976 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13977 if (*numSessionReturned > maxNumberSessions)
13978 *numSessionReturned = maxNumberSessions;
13979 else if (*numSessionReturned < 1) {
13980 *numSessionReturned = 0;
13981 return RETURN_OK;
13982 }
13983
developer033b37b2022-10-18 11:27:46 +080013984 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
developerfd7d2892022-09-13 16:44:53 +080013985 if ((f = popen(cmd, "r")) == NULL) {
13986 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13987 return RETURN_ERR;
13988 }
13989
13990 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013991 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013992 char *tmp = NULL;
13993 strcpy(buf, line);
13994 tmp = strtok(buf, " ");
13995 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13996 tmp = strtok(NULL, " ");
13997 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13998 tmp = strtok(NULL, " ");
13999 if (strstr(tmp, "t")) {
14000 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
14001 }
14002 if (strstr(tmp, "a")) {
14003 twtSessions[index].twtParameters.operation.announced = TRUE;
14004 }
14005 tmp = strtok(NULL, " ");
14006 exp = strtol(tmp, NULL, 10);
14007 tmp = strtok(NULL, " ");
14008 mantissa = strtol(tmp, NULL, 10);
14009 tmp = strtok(NULL, " ");
14010 duration = strtol(tmp, NULL, 10);
14011
14012 // only implicit supported
14013 twtSessions[index].twtParameters.operation.implicit = TRUE;
14014 // only individual agreement supported
14015 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
14016
14017 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
14018 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080014019 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080014020 // Overflow handling
14021 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
14022 } else {
14023 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
14024 }
14025 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
14026 index++;
14027 }
14028
14029 pclose(f);
14030 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14031 return RETURN_OK;
14032}