blob: a965254f9d395475fa79e858d8070d4a4c59689d [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));
developer77d395e2024-04-23 16:24:16 +08006261#ifdef SINGLE_WIPHY_SUPPORT
6262 sprintf(cmd, "iw phy phy0 interface add %s type __ap", interface_name);
6263#else
developer2f18b9f2023-03-17 19:32:57 +08006264 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
developer77d395e2024-04-23 16:24:16 +08006265#endif
developer2f18b9f2023-03-17 19:32:57 +08006266 _syscmd(cmd, buf, sizeof(buf));
6267 }
developer033b37b2022-10-18 11:27:46 +08006268 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006269 _syscmd(cmd, buf, sizeof(buf));
6270 }
6271 else {
developerd946fd62022-12-08 18:03:28 +08006272 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006273 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006274 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006275 _syscmd(cmd, buf, sizeof(buf));
6276 }
developera77d84b2023-02-22 16:10:50 +08006277
developer431128d2022-12-16 15:30:41 +08006278 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006279 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006280 _syscmd(cmd, buf, sizeof(buf));
6281 //Wait for wifi up/down to apply
6282 return RETURN_OK;
6283}
6284
6285// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6286INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6287{
developerd946fd62022-12-08 18:03:28 +08006288 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006289 char cmd[MAX_CMD_SIZE] = {'\0'};
6290 char buf[MAX_BUF_SIZE] = {'\0'};
6291
6292 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6293 return RETURN_ERR;
6294
6295 *output_bool = 0;
6296
6297 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6298 {
developerac6f1142022-12-20 19:26:35 +08006299 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006300 *output_bool = FALSE;
6301 return RETURN_OK;
6302 }
6303 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006304 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6305 }
6306
6307 return RETURN_OK;
6308}
6309
6310// Outputs the AP "Enabled" "Disabled" status from driver
6311INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6312{
6313 char cmd[128] = {0};
6314 char buf[128] = {0};
6315 BOOL output_bool;
6316
6317 if ( NULL == output_string)
6318 return RETURN_ERR;
6319 wifi_getApEnable(apIndex,&output_bool);
6320
6321 if(output_bool == 1)
6322 snprintf(output_string, 32, "Up");
6323 else
6324 snprintf(output_string, 32, "Disable");
6325
6326 return RETURN_OK;
6327}
6328
6329//Indicates whether or not beacons include the SSID name.
6330// outputs a 1 if SSID on the AP is enabled, else outputs 0
6331INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6332{
6333 //get the running status
6334 char config_file[MAX_BUF_SIZE] = {0};
6335 char buf[16] = {0};
6336
6337 if (!output)
6338 return RETURN_ERR;
6339
6340 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006341 if (!syn_flag)
6342 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6343 else
developer07ded1f2024-01-10 10:30:15 +08006344 snprintf(buf, sizeof(buf), "%s",vap_info[apIndex].ignore_broadcast_ssid);
developer1d57d002022-10-12 18:03:15 +08006345 // default is enable
6346 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6347 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006348
6349 return RETURN_OK;
6350}
6351
6352// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6353INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6354{
6355 //store the config, apply instantly
6356 char config_file[MAX_BUF_SIZE] = {0};
6357 struct params list;
6358
6359 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6360 list.name = "ignore_broadcast_ssid";
6361 list.value = enable?"0":"1";
6362
6363 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6364 wifi_hostapdWrite(config_file, &list, 1);
6365 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6366 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006367 wifi_reloadAp(apIndex);
developerefb790a2023-12-26 18:58:32 +08006368 snprintf(vap_info[apIndex].ignore_broadcast_ssid, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08006369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6370
6371 return RETURN_OK;
6372}
6373
6374//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6375INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6376{
6377 //get the running status
6378 if(!output_uint)
6379 return RETURN_ERR;
6380 *output_uint=16;
6381 return RETURN_OK;
6382}
6383
6384INT wifi_setApRetryLimit(INT apIndex, UINT number)
6385{
6386 //apply instantly
6387 return RETURN_ERR;
6388}
6389
6390//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6391INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6392{
6393 if(!output)
6394 return RETURN_ERR;
6395 *output=TRUE;
6396 return RETURN_OK;
6397}
6398
6399//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6400INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6401{
6402 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006403 char cmd[128] = {0};
6404 char buf[128] = {0};
6405 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006406 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006407
developer0b246d12022-09-30 15:24:20 +08006408 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006409
developer0b246d12022-09-30 15:24:20 +08006410 wifi_getMaxRadioNumber(&max_radio_num);
6411 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006412 phyId = radio_index_to_phy(radioIndex);
6413 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006414 _syscmd(cmd,buf, sizeof(buf));
6415
6416 if (strlen(buf) > 0)
6417 *output = true;
6418
6419 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006420
developer06a01d92022-09-07 16:32:39 +08006421 return RETURN_OK;
6422}
6423
6424//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6425INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6426{
6427 //get the running status from driver
6428 if(!output)
6429 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006430
6431 char config_file[MAX_BUF_SIZE] = {0};
6432 char buf[16] = {0};
6433
6434 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6435 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006436 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006437 *output = TRUE;
6438 else
6439 *output = FALSE;
6440
developer06a01d92022-09-07 16:32:39 +08006441 return RETURN_OK;
6442}
6443
6444// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6445INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6446{
6447 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006448 char config_file[MAX_BUF_SIZE] = {0};
6449 struct params list;
6450
6451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6452 list.name = "wmm_enabled";
6453 list.value = enable?"1":"0";
6454
6455 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6456 wifi_hostapdWrite(config_file, &list, 1);
6457 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6458 wifi_reloadAp(apIndex);
6459 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6460
6461 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006462}
6463
6464//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.
6465INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6466{
6467 //get the running status from driver
6468 if(!output)
6469 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006470
6471 char config_file[128] = {0};
6472 char buf[16] = {0};
6473
6474 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6475 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6476 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6477 *output = TRUE;
6478 else
6479 *output = FALSE;
6480
developer06a01d92022-09-07 16:32:39 +08006481 return RETURN_OK;
6482}
6483
6484// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6485INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6486{
6487 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006488 char config_file[MAX_BUF_SIZE] = {0};
6489 struct params list;
6490
6491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6492 list.name = "uapsd_advertisement_enabled";
6493 list.value = enable?"1":"0";
6494
6495 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6496 wifi_hostapdWrite(config_file, &list, 1);
6497 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6498 wifi_reloadAp(apIndex);
6499 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6500
6501 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006502}
6503
developer6daeb3f2022-09-30 13:36:39 +08006504// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006505INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6506{
developerd946fd62022-12-08 18:03:28 +08006507 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006508 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6509 char cmd[128] = {0};
6510 char buf[128] = {0};
6511 char ack_filepath[128] = {0};
6512 uint16_t bitmap = 0;
6513 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6514 FILE *f = NULL;
6515
6516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6517
6518 // Get current setting
6519 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6520 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6521 _syscmd(cmd, buf, sizeof(buf));
6522 if (strlen(buf) > 0)
6523 bitmap = strtoul(buf, NULL, 10);
6524
6525 bitmap = strtoul(buf, NULL, 10);
6526
6527 if (ackPolicy == TRUE) { // True, unset this class
6528 bitmap &= ~class_map[class];
6529 } else { // False, set this class
6530 bitmap |= class_map[class];
6531 }
6532
6533 f = fopen(ack_filepath, "w");
6534 if (f == NULL) {
6535 fprintf(stderr, "%s: fopen failed\n", __func__);
6536 return RETURN_ERR;
6537 }
6538 fprintf(f, "%hu", bitmap);
6539 fclose(f);
6540
developerac6f1142022-12-20 19:26:35 +08006541 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006542 return RETURN_ERR;
6543 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006544 _syscmd(cmd, buf, sizeof(buf));
6545
6546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6547 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006548}
6549
6550//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.
6551INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6552{
6553 //get the running status from driver
6554 if(!output_uint)
6555 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006556
6557 char output[16]={'\0'};
6558 char config_file[MAX_BUF_SIZE] = {0};
6559
6560 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006561 if (!syn_flag)
6562 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6563 else
developer07ded1f2024-01-10 10:30:15 +08006564 snprintf(output, sizeof(output), "%s", vap_info[apIndex].max_sta);
developer0947e1a2022-09-13 14:15:25 +08006565 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6566 else {
6567 int device_num = atoi(output);
6568 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6569 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6570 return RETURN_ERR;
6571 }
6572 else {
6573 *output_uint = device_num;
6574 }
6575 }
6576
developer06a01d92022-09-07 16:32:39 +08006577 return RETURN_OK;
6578}
6579
6580INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6581{
6582 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006583 char str[MAX_BUF_SIZE]={'\0'};
6584 char cmd[MAX_CMD_SIZE]={'\0'};
6585 struct params params;
6586 char config_file[MAX_BUF_SIZE] = {0};
6587
6588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006589 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006590 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006591 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006592 }
6593 sprintf(str, "%d", number);
6594 params.name = "max_num_sta";
6595 params.value = str;
6596
6597 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6598 int ret = wifi_hostapdWrite(config_file, &params, 1);
6599 if (ret) {
6600 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6601 ,__func__, ret);
6602 }
6603
6604 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6605 if (ret) {
6606 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6607 ,__func__, ret);
6608 }
6609 wifi_reloadAp(apIndex);
6610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6611
6612 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006613}
6614
6615//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.
6616INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6617{
6618 //get the current threshold
6619 if(!output_uint)
6620 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006621 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6622 if (*output_uint == 0)
6623 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006624 return RETURN_OK;
6625}
6626
6627INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6628{
6629 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006630 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6631 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006632 return RETURN_ERR;
6633}
6634
6635//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.
6636INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6637{
6638 if(!output_uint)
6639 return RETURN_ERR;
6640 *output_uint = 3;
6641 return RETURN_OK;
6642}
6643
6644//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6645INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6646{
6647 if(!output_uint)
6648 return RETURN_ERR;
6649 *output_uint = 3;
6650 return RETURN_OK;
6651}
6652
6653//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.
6654INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6655{
6656 if(!output_in_seconds)
6657 return RETURN_ERR;
6658 *output_in_seconds = 0;
6659 return RETURN_OK;
6660}
6661
6662//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
6663INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6664{
6665 if(!output || apIndex>=MAX_APS)
6666 return RETURN_ERR;
6667 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006668 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006669 return RETURN_OK;
6670}
6671
6672//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6673INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6674{
developer587c1b62022-09-27 15:58:59 +08006675 char config_file[128] = {0};
6676 char wpa[16] = {0};
6677 char key_mgmt[64] = {0};
6678 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006679 if (!output)
6680 return RETURN_ERR;
6681
6682 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006683 if (!syn_flag)
6684 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6685 else
developer07ded1f2024-01-10 10:30:15 +08006686 snprintf(wpa, sizeof(wpa), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006687
developer587c1b62022-09-27 15:58:59 +08006688 strcpy(output, "None");//Copying "None" to output string for default case
developerefb790a2023-12-26 18:58:32 +08006689 if (!syn_flag)
6690 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6691 else
developer07ded1f2024-01-10 10:30:15 +08006692 snprintf(key_mgmt, sizeof(key_mgmt), "%s", vap_info[apIndex].wpa_key_mgmt);
developer4a359672022-10-13 15:30:46 +08006693 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006694 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006695 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006696 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006697 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006698 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006699 snprintf(output, 32, "WPA-WPA2-Personal");
6700
developer72ec5572023-01-05 16:27:13 +08006701 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6702 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006703 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006704 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006705 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006706 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006707 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006708 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006709 snprintf(output, 32, "WPA-WPA2-Enterprise");
6710 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006711 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006712 snprintf(output, 32, "WPA3-Personal");
6713 else
developer4a359672022-10-13 15:30:46 +08006714 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006715 }
developer06a01d92022-09-07 16:32:39 +08006716
6717 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6718 return RETURN_OK;
6719#if 0
6720 //TODO: need to revisit below implementation
6721 char securityType[32], authMode[32];
6722 int enterpriseMode=0;
6723
6724 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6725 if(!output)
6726 return RETURN_ERR;
6727
6728 wifi_getApBeaconType(apIndex, securityType);
6729 strcpy(output,"None");//By default, copying "None" to output string
6730 if (strncmp(securityType,"None", strlen("None")) == 0)
6731 return RETURN_OK;
6732
6733 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6734 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6735
6736 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6737 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6738 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6739 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6740 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6741 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6742 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6743
6744 return RETURN_OK;
6745#endif
6746}
6747
6748INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6749{
6750 char securityType[32];
6751 char authMode[32];
6752
6753 //store settings and wait for wifi up to apply
6754 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6755 if(!encMode)
6756 return RETURN_ERR;
6757
developer06a01d92022-09-07 16:32:39 +08006758 if (strcmp(encMode, "None")==0)
6759 {
6760 strcpy(securityType,"None");
6761 strcpy(authMode,"None");
6762 }
6763 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6764 {
6765 strcpy(securityType,"WPAand11i");
6766 strcpy(authMode,"PSKAuthentication");
6767 }
6768 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6769 {
6770 strcpy(securityType,"WPAand11i");
6771 strcpy(authMode,"EAPAuthentication");
6772 }
6773 else if (strcmp(encMode, "WPA-Personal")==0)
6774 {
6775 strcpy(securityType,"WPA");
6776 strcpy(authMode,"PSKAuthentication");
6777 }
6778 else if (strcmp(encMode, "WPA-Enterprise")==0)
6779 {
6780 strcpy(securityType,"WPA");
6781 strcpy(authMode,"EAPAuthentication");
6782 }
6783 else if (strcmp(encMode, "WPA2-Personal")==0)
6784 {
6785 strcpy(securityType,"11i");
6786 strcpy(authMode,"PSKAuthentication");
6787 }
6788 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6789 {
6790 strcpy(securityType,"11i");
6791 strcpy(authMode,"EAPAuthentication");
6792 }
developer587c1b62022-09-27 15:58:59 +08006793 else if (strcmp(encMode, "WPA3-Personal") == 0)
6794 {
6795 strcpy(securityType,"11i");
6796 strcpy(authMode,"SAEAuthentication");
6797 }
developer4a359672022-10-13 15:30:46 +08006798 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006799 {
6800 strcpy(securityType, "11i");
6801 strcpy(authMode, "PSK-SAEAuthentication");
6802 }
developer587c1b62022-09-27 15:58:59 +08006803 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6804 {
6805 strcpy(securityType,"11i");
6806 strcpy(authMode,"EAP_192-bit_Authentication");
6807 }
developer5c9fee82023-01-13 14:44:16 +08006808 else if (strcmp(encMode, "OWE") == 0)
6809 {
6810 strcpy(securityType,"11i");
6811 strcpy(authMode,"Enhanced_Open");
6812 }
developer06a01d92022-09-07 16:32:39 +08006813 else
6814 {
6815 strcpy(securityType,"None");
6816 strcpy(authMode,"None");
6817 }
6818 wifi_setApBeaconType(apIndex, securityType);
6819 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6820 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6821
6822 return RETURN_OK;
6823}
6824
6825
developer4b102122023-02-15 10:53:03 +08006826// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006827//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006828INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6829{
developer30423732022-12-01 16:17:49 +08006830 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006831 char config_file[MAX_BUF_SIZE] = {0};
6832
6833 if(output_string==NULL)
6834 return RETURN_ERR;
6835
6836 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006837 if (!syn_flag)
6838 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6839 else
developer07ded1f2024-01-10 10:30:15 +08006840 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006841 if(strcmp(buf,"0")==0)
6842 {
6843 printf("wpa_mode is %s ......... \n",buf);
6844 return RETURN_ERR;
6845 }
6846
6847 wifi_dbg_printf("\nFunc=%s\n",__func__);
6848 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006849 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006850 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6851
6852 return RETURN_OK;
6853}
6854
developer4b102122023-02-15 10:53:03 +08006855// Set PreSharedKey associated with a Access Point.
6856// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006857INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6858{
6859 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6860 struct params params={'\0'};
6861 int ret;
6862 char config_file[MAX_BUF_SIZE] = {0};
6863
6864 if(NULL == preSharedKey)
6865 return RETURN_ERR;
6866
developer4b102122023-02-15 10:53:03 +08006867 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006868
developer4b102122023-02-15 10:53:03 +08006869 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006870 {
developer4b102122023-02-15 10:53:03 +08006871 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006872 return RETURN_ERR;
6873 }
6874 params.value = preSharedKey;
6875 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6876 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006877 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006878 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006879 wifi_reloadAp(apIndex);
6880 }
developer06a01d92022-09-07 16:32:39 +08006881 return ret;
6882 //TODO: call hostapd_cli for dynamic_config_control
6883}
6884
6885//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6886// outputs the passphrase, maximum 63 characters
6887INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6888{
6889 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6890
6891 wifi_dbg_printf("\nFunc=%s\n",__func__);
6892 if (NULL == output_string)
6893 return RETURN_ERR;
6894
6895 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006896 if (!syn_flag)
6897 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6898 else
developer07ded1f2024-01-10 10:30:15 +08006899 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006900 if(strcmp(buf,"0")==0)
6901 {
6902 printf("wpa_mode is %s ......... \n",buf);
6903 return RETURN_ERR;
6904 }
6905
developerefb790a2023-12-26 18:58:32 +08006906 if (!syn_flag)
6907 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6908 else
developer07ded1f2024-01-10 10:30:15 +08006909 snprintf(output_string, 64, "%s", vap_info[apIndex].wpa_passphrase);
developer06a01d92022-09-07 16:32:39 +08006910 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6911
6912 return RETURN_OK;
6913}
6914
6915// sets the passphrase enviornment variable, max 63 characters
6916INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6917{
6918 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6919 struct params params={'\0'};
6920 char config_file[MAX_BUF_SIZE] = {0};
6921 int ret;
6922
6923 if(NULL == passPhrase)
6924 return RETURN_ERR;
6925
6926 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6927 {
6928 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6929 return RETURN_ERR;
6930 }
6931 params.name = "wpa_passphrase";
6932 params.value = passPhrase;
6933 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6934 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006935 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006936 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006937 wifi_reloadAp(apIndex);
6938 }
developerefb790a2023-12-26 18:58:32 +08006939 snprintf(vap_info[apIndex].wpa_passphrase, MAX_BUF_SIZE, "%s", passPhrase);
developer06a01d92022-09-07 16:32:39 +08006940
6941 return ret;
6942}
6943
6944//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.
6945INT wifi_setApSecurityReset(INT apIndex)
6946{
developer8d583982022-09-20 11:28:22 +08006947 char original_config_file[64] = {0};
6948 char current_config_file[64] = {0};
6949 char buf[64] = {0};
6950 char cmd[64] = {0};
6951 char wpa[4] = {0};
6952 char wpa_psk[64] = {0};
6953 char wpa_passphrase[64] = {0};
6954 char wpa_psk_file[128] = {0};
6955 char wpa_key_mgmt[64] = {0};
6956 char wpa_pairwise[32] = {0};
6957 wifi_band band;
6958 struct params list[6];
6959
6960 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6961
6962 band = wifi_index_to_band(apIndex);
6963 if (band == band_2_4)
6964 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006965 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006966 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006967 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006968 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6969 else
6970 return RETURN_ERR;
6971
6972 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6973 list[0].name = "wpa";
6974 list[0].value = wpa;
6975
6976 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6977 list[1].name = "wpa_psk";
6978 list[1].value = wpa_psk;
6979
6980 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6981 list[2].name = "wpa_passphrase";
6982 list[2].value = wpa_passphrase;
6983
6984 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6985
6986 if (strlen(wpa_psk_file) == 0)
6987 strcpy(wpa_psk_file, PSK_FILE);
6988
6989 if (access(wpa_psk_file, F_OK) != 0) {
6990 sprintf(cmd, "touch %s", wpa_psk_file);
6991 _syscmd(cmd, buf, sizeof(buf));
6992 }
6993 list[3].name = "wpa_psk_file";
6994 list[3].value = wpa_psk_file;
6995
6996 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6997 list[4].name = "wpa_key_mgmt";
6998 list[4].value = wpa_key_mgmt;
6999
7000 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
7001 list[5].name = "wpa_pairwise";
7002 list[5].value = wpa_pairwise;
7003
7004 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7005 wifi_hostapdWrite(current_config_file, list, 6);
7006
7007 wifi_setApEnable(apIndex, FALSE);
7008 wifi_setApEnable(apIndex, TRUE);
7009
7010 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7011 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007012}
7013
7014//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).
7015INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7016{
developer8f2ddd52022-09-13 15:39:24 +08007017 char config_file[64] = {0};
7018 char buf[64] = {0};
7019 char cmd[256] = {0};
7020
7021 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7022
developer06a01d92022-09-07 16:32:39 +08007023 if(!IP_output || !Port_output || !RadiusSecret_output)
7024 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08007025
developer8f2ddd52022-09-13 15:39:24 +08007026 // Read the first matched config
7027 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7028 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7029 _syscmd(cmd, buf, sizeof(buf));
7030 strncpy(IP_output, buf, 64);
7031
7032 memset(buf, 0, sizeof(buf));
7033 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7034 _syscmd(cmd, buf, sizeof(buf));
7035 *Port_output = atoi(buf);
7036
7037 memset(buf, 0, sizeof(buf));
7038 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7039 _syscmd(cmd, buf, sizeof(buf));
7040 strncpy(RadiusSecret_output, buf, 64);
7041
7042 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007043 return RETURN_OK;
7044}
7045
7046INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7047{
developer8f2ddd52022-09-13 15:39:24 +08007048 char config_file[64] = {0};
7049 char port_str[8] = {0};
7050 char cmd[256] = {0};
7051 char buf[128] = {0};
7052
7053 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007054 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7055 return RETURN_ERR;
7056
7057 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7058 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007059
7060 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7061
7062 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7063 _syscmd(cmd, buf, sizeof(buf));
7064 memset(cmd, 0, sizeof(cmd));
7065
7066 snprintf(port_str, sizeof(port_str), "%d", port);
7067 if (strlen(buf) == 0)
7068 // Append
7069 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7070 "auth_server_addr=%s\\n"
7071 "auth_server_port=%s\\n"
7072 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7073 else {
7074 // Delete the three lines setting after the "# radius 1" comment
7075 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7076 _syscmd(cmd, buf, sizeof(buf));
7077 memset(cmd, 0, sizeof(cmd));
7078 // Use "# radius 1" comment to find the location to insert the radius setting
7079 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7080 "# radius 1\\n"
7081 "auth_server_addr=%s\\n"
7082 "auth_server_port=%s\\n"
7083 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7084 }
7085 if(_syscmd(cmd, buf, sizeof(buf))) {
7086 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7087 return RETURN_ERR;
7088 }
7089
7090 wifi_reloadAp(apIndex);
7091 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7092 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007093}
7094
7095INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7096{
developer8f2ddd52022-09-13 15:39:24 +08007097 char config_file[64] = {0};
7098 char buf[64] = {0};
7099 char cmd[256] = {0};
7100
7101 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7102
developer06a01d92022-09-07 16:32:39 +08007103 if(!IP_output || !Port_output || !RadiusSecret_output)
7104 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007105
7106 // Read the second matched config
7107 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7108 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7109 _syscmd(cmd, buf, sizeof(buf));
7110 strncpy(IP_output, buf, 64);
7111
7112 memset(buf, 0, sizeof(buf));
7113 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7114 _syscmd(cmd, buf, sizeof(buf));
7115 *Port_output = atoi(buf);
7116
7117 memset(buf, 0, sizeof(buf));
7118 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7119 _syscmd(cmd, buf, sizeof(buf));
7120 strncpy(RadiusSecret_output, buf, 64);
7121
7122 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007123 return RETURN_OK;
7124}
7125
7126INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7127{
developer8f2ddd52022-09-13 15:39:24 +08007128 char config_file[64] = {0};
7129 char port_str[8] = {0};
7130 char cmd[256] = {0};
7131 char buf[128] = {0};
7132
7133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007134 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7135 return RETURN_ERR;
7136
7137 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7138 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007139
7140 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7141
7142 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7143 _syscmd(cmd, buf, sizeof(buf));
7144 memset(cmd, 0, sizeof(cmd));
7145
7146 snprintf(port_str, sizeof(port_str), "%d", port);
7147 if (strlen(buf) == 0)
7148 // Append
7149 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7150 "auth_server_addr=%s\\n"
7151 "auth_server_port=%s\\n"
7152 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7153 else {
7154 // Delete the three lines setting after the "# radius 2" comment
7155 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7156 _syscmd(cmd, buf, sizeof(buf));
7157 memset(cmd, 0, sizeof(cmd));
7158 // Use "# radius 2" comment to find the location to insert the radius setting
7159 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7160 "# radius 2\\n"
7161 "auth_server_addr=%s\\n"
7162 "auth_server_port=%s\\n"
7163 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7164 }
7165 if(_syscmd(cmd, buf, sizeof(buf))) {
7166 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7167 return RETURN_ERR;
7168 }
7169
7170 wifi_reloadAp(apIndex);
7171 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7172 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007173}
7174
7175//RadiusSettings
7176INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7177{
7178 if(!output)
7179 return RETURN_ERR;
7180
7181 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7182 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7183 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7184 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7185 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7186 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.
7187 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7188 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7189 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7190 //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.
7191
7192 return RETURN_OK;
7193}
7194
7195INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7196{
7197 //store the paramters, and apply instantly
7198 return RETURN_ERR;
7199}
7200
7201//Device.WiFi.AccessPoint.{i}.WPS.Enable
7202//Enables or disables WPS functionality for this access point.
7203// outputs the WPS enable state of this ap in output_bool
7204INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7205{
developerd946fd62022-12-08 18:03:28 +08007206 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007207 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer613892e2023-09-21 16:33:35 +08007208
7209 *output_bool=FALSE;
developer5b398df2022-11-17 20:39:48 +08007210 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007211 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007212 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer613892e2023-09-21 16:33:35 +08007213 return RETURN_OK;
developerd946fd62022-12-08 18:03:28 +08007214 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007215 _syscmd(cmd, buf, sizeof(buf));
7216 if(strstr(buf, "configured"))
7217 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08007218
7219 return RETURN_OK;
developer613892e2023-09-21 16:33:35 +08007220}
developer06a01d92022-09-07 16:32:39 +08007221
7222//Device.WiFi.AccessPoint.{i}.WPS.Enable
7223// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7224INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7225{
7226 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007227 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007228 struct params params;
7229
developer06a01d92022-09-07 16:32:39 +08007230 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7231 //store the paramters, and wait for wifi up to apply
7232 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007233 if (enable == TRUE) {
7234 wifi_getApBeaconType(apIndex, buf);
7235 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7236 params.value = "1";
7237 else // If ap set encryption
7238 params.value = "2";
7239 } else {
7240 params.value = "0";
7241 }
developer06a01d92022-09-07 16:32:39 +08007242
7243 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7244 wifi_hostapdWrite(config_file, &params, 1);
7245 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7246 wifi_reloadAp(apIndex);
7247
7248 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7249 return RETURN_OK;
7250}
7251
7252//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
7253INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7254{
7255 if(!output)
7256 return RETURN_ERR;
7257 snprintf(output, 128, "PushButton,PIN");
7258 return RETURN_OK;
7259}
7260
7261//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7262//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.
7263// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7264INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7265{
7266 if(!output)
7267 return RETURN_ERR;
7268 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7269
7270 return RETURN_OK;
7271}
7272
7273//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7274// 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
7275INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7276{
7277 //apply instantly. No setting need to be stored.
7278 char methods[MAX_BUF_SIZE], *token, *next_token;
7279 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7280 struct params params;
7281
developer5b398df2022-11-17 20:39:48 +08007282 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007283 return RETURN_ERR;
7284 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7285 //store the paramters, and wait for wifi up to apply
7286
7287 snprintf(methods, sizeof(methods), "%s", methodString);
7288 for(token=methods; *token; token=next_token)
7289 {
7290 strtok_r(token, ",", &next_token);
7291 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7292 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7293 else if(*token=='E')
7294 {
7295 if(!strcmp(methods, "Ethernet"))
7296 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7297 else if(!strcmp(methods, "ExternalNFCToken"))
7298 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7299 else
7300 printf("%s: Unknown WpsConfigMethod\n", __func__);
7301 }
7302 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7303 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7304 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7305 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7306 else if(*token=='P' )
7307 {
7308 if(!strcmp(token, "PushButton"))
developer894affa2023-05-10 18:13:19 +08007309 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer06a01d92022-09-07 16:32:39 +08007310 else if(!strcmp(token, "PIN"))
7311 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7312 else
7313 printf("%s: Unknown WpsConfigMethod\n", __func__);
7314 }
7315 else
7316 printf("%s: Unknown WpsConfigMethod\n", __func__);
7317 }
7318 params.name = "config_methods";
7319 params.value = config_methods;
7320 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7321 wifi_hostapdWrite(config_file, &params, 1);
7322 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7323 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7324
7325 return RETURN_OK;
7326}
7327
7328// outputs the pin value, ulong_pin must be allocated by the caller
7329INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7330{
7331 char buf[MAX_BUF_SIZE] = {0};
7332 char cmd[MAX_CMD_SIZE] = {0};
7333
developer5b398df2022-11-17 20:39:48 +08007334 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007335 return RETURN_ERR;
7336 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7337 _syscmd(cmd, buf, sizeof(buf));
7338 if(strlen(buf) > 0)
7339 *output_ulong=strtoul(buf, NULL, 10);
7340
7341 return RETURN_OK;
7342}
7343
7344// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7345INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7346{
7347 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7348 char ap_pin[16] = {0};
7349 char buf[MAX_BUF_SIZE] = {0};
7350 char config_file[MAX_BUF_SIZE] = {0};
7351 ULONG prev_pin = 0;
7352 struct params params;
7353
developer06a01d92022-09-07 16:32:39 +08007354 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7355 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7356 params.name = "ap_pin";
7357 params.value = ap_pin;
7358 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7359 wifi_hostapdWrite(config_file, &params, 1);
7360 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7361 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7362
7363 return RETURN_OK;
7364}
7365
7366// Output string is either Not configured or Configured, max 32 characters
7367INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7368{
developerd946fd62022-12-08 18:03:28 +08007369 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007370 char cmd[MAX_CMD_SIZE];
7371 char buf[MAX_BUF_SIZE]={0};
7372
developer5b398df2022-11-17 20:39:48 +08007373 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007374 return RETURN_ERR;
7375 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7376 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007377 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007378 return RETURN_ERR;
7379 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007380 _syscmd(cmd, buf, sizeof(buf));
7381
developer348e3d92022-09-13 14:48:41 +08007382 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007383 snprintf(output_string, 32, "Configured");
7384 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7385
7386 return RETURN_OK;
7387}
7388
7389// sets the WPS pin for this AP
7390INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7391{
developerd946fd62022-12-08 18:03:28 +08007392 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007393 char cmd[MAX_CMD_SIZE];
7394 char buf[MAX_BUF_SIZE]={0};
7395 BOOL enable;
7396
developer06a01d92022-09-07 16:32:39 +08007397 wifi_getApEnable(apIndex, &enable);
7398 if (!enable)
7399 return RETURN_ERR;
7400 wifi_getApWpsEnable(apIndex, &enable);
7401 if (!enable)
7402 return RETURN_ERR;
7403
developerac6f1142022-12-20 19:26:35 +08007404 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007405 return RETURN_ERR;
7406 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007407 _syscmd(cmd, buf, sizeof(buf));
7408 if((strstr(buf, "OK"))!=NULL)
7409 return RETURN_OK;
7410
7411 return RETURN_ERR;
7412}
7413
7414// This function is called when the WPS push button has been pressed for this AP
7415INT wifi_setApWpsButtonPush(INT apIndex)
7416{
7417 char cmd[MAX_CMD_SIZE];
7418 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007419 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007420 BOOL enable=FALSE;
7421
developer06a01d92022-09-07 16:32:39 +08007422 wifi_getApEnable(apIndex, &enable);
7423 if (!enable)
7424 return RETURN_ERR;
7425
7426 wifi_getApWpsEnable(apIndex, &enable);
7427 if (!enable)
7428 return RETURN_ERR;
7429
developerac6f1142022-12-20 19:26:35 +08007430 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007431 return RETURN_ERR;
7432
developer900e2b72023-05-23 10:23:48 +08007433 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 +08007434 _syscmd(cmd, buf, sizeof(buf));
7435
7436 if((strstr(buf, "OK"))!=NULL)
7437 return RETURN_OK;
7438 return RETURN_ERR;
7439}
7440
7441// cancels WPS mode for this AP
7442INT wifi_cancelApWPS(INT apIndex)
7443{
developerd946fd62022-12-08 18:03:28 +08007444 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007445 char cmd[MAX_CMD_SIZE];
7446 char buf[MAX_BUF_SIZE]={0};
7447
developerac6f1142022-12-20 19:26:35 +08007448 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007449 return RETURN_ERR;
7450 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007451 _syscmd(cmd,buf, sizeof(buf));
7452
7453 if((strstr(buf, "OK"))!=NULL)
7454 return RETURN_OK;
7455 return RETURN_ERR;
7456}
7457
7458//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7459//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7460INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7461{
developerd946fd62022-12-08 18:03:28 +08007462 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007463 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007464 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007465 char cmd[256] = {0}, buf[2048] = {0};
7466 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007467 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007468 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007469 wifi_associated_dev_t *dev=NULL;
7470
7471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7472 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007473 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007474 return RETURN_ERR;
7475 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007476 _syscmd(cmd,buf,sizeof(buf));
7477 *output_array_size = atoi(buf);
7478
7479 if (*output_array_size <= 0)
7480 return RETURN_OK;
7481
7482 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7483 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007484 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007485 _syscmd(cmd,buf,sizeof(buf));
7486 f = fopen("/tmp/connected_devices.txt", "r");
7487 if (f==NULL)
7488 {
7489 *output_array_size=0;
7490 return RETURN_ERR;
7491 }
developer30423732022-12-01 16:17:49 +08007492 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007493 {
7494 param = strtok(line,"=");
7495 value = strtok(NULL,"=");
7496
7497 if( strcmp("flags",param) == 0 )
7498 {
7499 value[strlen(value)-1]='\0';
7500 if(strstr (value,"AUTHORIZED") != NULL )
7501 {
7502 dev[auth_temp].cli_AuthenticationState = 1;
7503 dev[auth_temp].cli_Active = 1;
7504 auth_temp++;
7505 read_flag=1;
7506 }
7507 }
7508 if(read_flag==1)
7509 {
7510 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7511 {
7512 value[strlen(value)-1]='\0';
7513 sscanf(value, "%x:%x:%x:%x:%x:%x",
7514 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7515 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7516 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7517 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7518 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7519 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7520 mac_temp++;
7521 read_flag=0;
7522 }
7523 }
7524 }
7525 *output_array_size = auth_temp;
7526 auth_temp=0;
7527 mac_temp=0;
7528 free(line);
7529 fclose(f);
7530 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7531 return RETURN_OK;
7532}
7533
7534#define MACADDRESS_SIZE 6
7535
7536INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7537{
7538 FILE *fp = NULL;
7539 char str[MAX_BUF_SIZE] = {0};
7540 int wificlientindex = 0 ;
7541 int count = 0;
7542 int signalstrength = 0;
7543 int arr[MACADDRESS_SIZE] = {0};
7544 unsigned char mac[MACADDRESS_SIZE] = {0};
7545 UINT wifi_count = 0;
7546 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7547 char pipeCmd[MAX_CMD_SIZE] = {0};
7548
7549 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7550 *output_array_size = 0;
7551 *associated_dev_array = NULL;
7552
7553 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7554 fp = popen(pipeCmd, "r");
7555 if (fp == NULL)
7556 {
7557 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7558 return RETURN_ERR;
7559 }
7560
7561 /* Read the output a line at a time - output it. */
7562 fgets(str, sizeof(str)-1, fp);
7563 wifi_count = (unsigned int) atoi ( str );
7564 *output_array_size = wifi_count;
7565 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7566 pclose(fp);
7567
7568 if(wifi_count == 0)
7569 {
7570 return RETURN_OK;
7571 }
7572 else
7573 {
7574 wifi_associated_dev3_t* temp = NULL;
7575 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7576 if(temp == NULL)
7577 {
7578 printf("Error Statement. Insufficient memory \n");
7579 return RETURN_ERR;
7580 }
7581
7582 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7583 system(pipeCmd);
7584 memset(pipeCmd,0,sizeof(pipeCmd));
7585 if(apIndex == 0)
7586 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7587 else if(apIndex == 1)
7588 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7589 system(pipeCmd);
7590
7591 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7592 if(fp == NULL)
7593 {
7594 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007595 free(temp);
developer06a01d92022-09-07 16:32:39 +08007596 return RETURN_ERR;
7597 }
7598 fclose(fp);
7599
developer30423732022-12-01 16:17:49 +08007600 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007601 fp = popen(pipeCmd, "r");
7602 if(fp)
7603 {
7604 for(count =0 ; count < wifi_count; count++)
7605 {
7606 fgets(str, MAX_BUF_SIZE, fp);
7607 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7608 {
7609 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7610 {
7611 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7612
7613 }
7614 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7615 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]);
7616 }
7617 temp[count].cli_AuthenticationState = 1; //TODO
7618 temp[count].cli_Active = 1; //TODO
7619 }
7620 pclose(fp);
7621 }
7622
developer30423732022-12-01 16:17:49 +08007623 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 +08007624 fp = popen(pipeCmd, "r");
7625 if(fp)
7626 {
7627 pclose(fp);
7628 }
7629 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7630 if(fp)
7631 {
7632 for(count =0 ; count < wifi_count ;count++)
7633 {
7634 fgets(str, MAX_BUF_SIZE, fp);
7635 signalstrength = atoi(str);
7636 temp[count].cli_SignalStrength = signalstrength;
7637 temp[count].cli_RSSI = signalstrength;
7638 temp[count].cli_SNR = signalstrength + 95;
7639 }
7640 pclose(fp);
7641 }
7642
7643
7644 if((apIndex == 0) || (apIndex == 4))
7645 {
7646 for(count =0 ; count < wifi_count ;count++)
7647 {
7648 strcpy(temp[count].cli_OperatingStandard,"g");
7649 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7650 }
7651
7652 //BytesSent
developer30423732022-12-01 16:17:49 +08007653 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 +08007654 fp = popen(pipeCmd, "r");
7655 if(fp)
7656 {
7657 pclose(fp);
7658 }
7659 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7660 if(fp)
7661 {
7662 for (count = 0; count < wifi_count; count++)
7663 {
7664 fgets(str, MAX_BUF_SIZE, fp);
7665 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7666 }
7667 pclose(fp);
7668 }
7669
7670 //BytesReceived
developer30423732022-12-01 16:17:49 +08007671 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 +08007672 fp = popen(pipeCmd, "r");
7673 if (fp)
7674 {
7675 pclose(fp);
7676 }
7677 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7678 if (fp)
7679 {
7680 for (count = 0; count < wifi_count; count++)
7681 {
7682 fgets(str, MAX_BUF_SIZE, fp);
7683 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7684 }
7685 pclose(fp);
7686 }
7687
7688 //PacketsSent
developer30423732022-12-01 16:17:49 +08007689 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 +08007690 fp = popen(pipeCmd, "r");
7691 if (fp)
7692 {
7693 pclose(fp);
7694 }
7695
7696 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7697 if (fp)
7698 {
7699 for (count = 0; count < wifi_count; count++)
7700 {
7701 fgets(str, MAX_BUF_SIZE, fp);
7702 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7703 }
7704 pclose(fp);
7705 }
7706
7707 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007708 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 +08007709 fp = popen(pipeCmd, "r");
7710 if (fp)
7711 {
7712 pclose(fp);
7713 }
7714 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7715 if (fp)
7716 {
7717 for (count = 0; count < wifi_count; count++)
7718 {
7719 fgets(str, MAX_BUF_SIZE, fp);
7720 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7721 }
7722 pclose(fp);
7723 }
7724
7725 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007726 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 +08007727 fp = popen(pipeCmd, "r");
7728 if (fp)
7729 {
7730 pclose(fp);
7731 }
7732 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7733 if (fp)
7734 {
7735 for (count = 0; count < wifi_count; count++)
7736 {
7737 fgets(str, MAX_BUF_SIZE, fp);
7738 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7739 }
7740 pclose(fp);
7741 }
7742
7743 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007744 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 +08007745 fp = popen(pipeCmd, "r");
7746 if (fp)
7747 {
7748 pclose(fp);
7749 }
7750 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7751 if (fp)
7752 {
7753 for (count = 0; count < wifi_count; count++)
7754 {
7755 fgets(str, MAX_BUF_SIZE, fp);
7756 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7757 }
7758 pclose(fp);
7759 }
7760
7761 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007762 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 +08007763 fp = popen(pipeCmd, "r");
7764 if (fp)
7765 {
7766 pclose(fp);
7767 }
7768 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7769 if (fp)
7770 {
7771 for (count = 0; count < wifi_count; count++)
7772 {
7773 fgets(str, MAX_BUF_SIZE, fp);
7774 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7775 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7776 }
7777 pclose(fp);
7778 }
7779
7780 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007781 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 +08007782 fp = popen(pipeCmd, "r");
7783 if (fp)
7784 {
7785 pclose(fp);
7786 }
7787 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7788 if (fp)
7789 {
7790 for (count = 0; count < wifi_count; count++)
7791 {
7792 fgets(str, MAX_BUF_SIZE, fp);
7793 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7794 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7795 }
7796 pclose(fp);
7797 }
7798
7799 }
7800 else if ((apIndex == 1) || (apIndex == 5))
7801 {
7802 for (count = 0; count < wifi_count; count++)
7803 {
7804 strcpy(temp[count].cli_OperatingStandard, "a");
7805 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7806 temp[count].cli_BytesSent = 0;
7807 temp[count].cli_BytesReceived = 0;
7808 temp[count].cli_LastDataUplinkRate = 0;
7809 temp[count].cli_LastDataDownlinkRate = 0;
7810 temp[count].cli_PacketsSent = 0;
7811 temp[count].cli_PacketsReceived = 0;
7812 temp[count].cli_ErrorsSent = 0;
7813 }
7814 }
7815
7816 for (count = 0; count < wifi_count; count++)
7817 {
7818 temp[count].cli_Retransmissions = 0;
7819 temp[count].cli_DataFramesSentAck = 0;
7820 temp[count].cli_DataFramesSentNoAck = 0;
7821 temp[count].cli_MinRSSI = 0;
7822 temp[count].cli_MaxRSSI = 0;
7823 strncpy(temp[count].cli_InterferenceSources, "", 64);
7824 memset(temp[count].cli_IPAddress, 0, 64);
7825 temp[count].cli_RetransCount = 0;
7826 temp[count].cli_FailedRetransCount = 0;
7827 temp[count].cli_RetryCount = 0;
7828 temp[count].cli_MultipleRetryCount = 0;
7829 }
7830 *associated_dev_array = temp;
7831 }
7832 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7833 return RETURN_OK;
7834}
7835
7836int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7837{
7838 FILE *fp = NULL;
7839 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7840 char cmd[MAX_CMD_SIZE];
7841 int count = 0;
7842
7843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7844 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7845 fp = popen(cmd,"r");
7846 if(fp == NULL)
7847 {
7848 printf("Failed to run command in Function %s\n",__FUNCTION__);
7849 return 0;
7850 }
7851 if(fgets(path, sizeof(path)-1, fp) != NULL)
7852 {
7853 for(count=0;path[count]!='\n';count++)
7854 status[count]=path[count];
7855 status[count]='\0';
7856 }
7857 strcpy(wifi_status,status);
7858 pclose(fp);
7859 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7860 return RETURN_OK;
7861}
7862
7863/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7864struct hostapd_sta_param {
7865 char key[50];
7866 char value[100];
7867}
7868
7869static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7870 int i = 0;
7871
7872 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7873 if (strncmp(params[i].key,key,50) == 0){
7874 return &params[i].value;
7875 }
7876 i++;
7877 }
7878 return NULL;
7879
7880} */
7881
7882static unsigned int count_occurences(const char *buf, const char *word)
7883{
7884 unsigned int n = 0;
7885 char *ptr = strstr(buf, word);
7886
7887 while (ptr++) {
7888 n++;
7889 ptr = strstr(ptr, word);
7890 }
7891
7892 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7893 return n;
7894}
7895
7896static const char *get_line_from_str_buf(const char *buf, char *line)
7897{
7898 int i;
7899 int n = strlen(buf);
7900
7901 for (i = 0; i < n; i++) {
7902 line[i] = buf[i];
7903 if (buf[i] == '\n') {
7904 line[i] = '\0';
7905 return &buf[i + 1];
7906 }
7907 }
7908
7909 return NULL;
7910}
7911
developer9a9f46e2023-11-09 09:22:42 +08007912static INT wifi_getAssocConnectMode(INT apIndex, CHAR *input_string, CHAR *OperatingStandard)
7913{
7914 wifi_band band;
7915 int ieee80211_mode = 0;
7916
7917 if (!input_string || !OperatingStandard)
7918 return RETURN_ERR;
7919
7920 band = wifi_index_to_band(apIndex);
7921
7922 if (strstr(input_string, "HE"))
7923 ieee80211_mode = WIFI_MODE_AX;
7924 else if (strstr(input_string, "VHT"))
7925 ieee80211_mode = WIFI_MODE_AC;
7926 else if (strstr(input_string, "EHT"))
7927 ieee80211_mode = WIFI_MODE_BE;
7928
7929 switch (ieee80211_mode) {
7930 case WIFI_MODE_AC:
7931 strncpy(OperatingStandard, "ac", 2);
7932 break;
7933 case WIFI_MODE_AX:
7934 strncpy(OperatingStandard, "ax", 2);
7935 break;
7936 case WIFI_MODE_BE:
7937 strncpy(OperatingStandard, "be", 2);
7938 break;
7939 default:
7940 if(band == band_2_4)
7941 strncpy(OperatingStandard,"b,g,n", 5);
7942 else if(band == band_5)
7943 strncpy(OperatingStandard,"a,n", 3);
7944 else if(band == band_6)
7945 strncpy(OperatingStandard,"ax", 2);
7946 else {
7947 wifi_dbg_printf("%s: failed to parse band %d\n", __FUNCTION__, band);
7948 return RETURN_ERR;
7949 }
7950 }
7951
7952
7953 return RETURN_OK;
7954}
7955
developer06a01d92022-09-07 16:32:39 +08007956INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7957{
7958 unsigned int assoc_cnt = 0;
7959 char interface_name[50] = {0};
7960 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7961 char cmd[MAX_CMD_SIZE] = {'\0'};
7962 char line[256] = {'\0'};
7963 int i = 0;
7964 int ret = 0;
7965 const char *ptr = NULL;
7966 char *key = NULL;
7967 char *val = NULL;
7968 wifi_associated_dev3_t *temp = NULL;
7969 int rssi;
7970
7971 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7972
7973 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7974 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7975 return RETURN_ERR;
7976 }
7977
7978 // Example filtered output of 'iw dev' command:
7979 // Station 0a:69:72:10:d2:fa (on wifi0)
7980 // signal avg:-67 [-71, -71] dBm
7981 // Station 28:c2:1f:25:5f:99 (on wifi0)
7982 // signal avg:-67 [-71, -70] dBm
developer9a9f46e2023-11-09 09:22:42 +08007983 if (sprintf(cmd,"iw dev %s station dump | tr -d '\t' | grep -E 'Station|signal avg"
7984 "|tx bitrate|rx bitrate'", interface_name) < 0) {
7985 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
developer06a01d92022-09-07 16:32:39 +08007986 return RETURN_ERR;
7987 }
7988
7989 ret = _syscmd(cmd, buf, sizeof(buf));
7990 if (ret == RETURN_ERR) {
7991 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7992 return RETURN_ERR;
7993 }
7994
7995 *output_array_size = count_occurences(buf, "Station");
7996 if (*output_array_size == 0) return RETURN_OK;
7997
7998 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7999 if (temp == NULL) {
8000 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
8001 return RETURN_ERR;
8002 }
8003 *associated_dev_array = temp;
8004
8005 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
8006 ptr = get_line_from_str_buf(buf, line);
8007 i = -1;
8008 while (ptr) {
8009 if (strstr(line, "Station")) {
8010 i++;
8011 key = strtok(line, " ");
8012 val = strtok(NULL, " ");
8013 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8014 &temp[i].cli_MACAddress[0],
8015 &temp[i].cli_MACAddress[1],
8016 &temp[i].cli_MACAddress[2],
8017 &temp[i].cli_MACAddress[3],
8018 &temp[i].cli_MACAddress[4],
8019 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8020 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8021 free(*associated_dev_array);
8022 return RETURN_ERR;
8023 }
8024 }
8025 else if (i < 0) {
developer9a9f46e2023-11-09 09:22:42 +08008026 wifi_dbg_printf("%s: not find station\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +08008027 ptr = get_line_from_str_buf(ptr, line);
8028 continue; // We didn't detect 'station' entry yet
8029 }
8030 else if (strstr(line, "signal avg")) {
8031 key = strtok(line, ":");
8032 val = strtok(NULL, " ");
8033 if (sscanf(val, "%d", &rssi) <= 0 ) {
8034 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8035 free(*associated_dev_array);
8036 return RETURN_ERR;
8037 }
8038 temp[i].cli_RSSI = rssi;
8039 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8040 }
developer9a9f46e2023-11-09 09:22:42 +08008041 else if (strstr(line, "tx bitrate")) {
8042 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8043 if (ret == RETURN_ERR) {
8044 wifi_dbg_printf("%s: failed to execute tx get assoc connect mode command.\n", __FUNCTION__);
8045 return ret;
8046 }
8047 }
8048 else if (strstr(line, "rx bitrate")) {
8049 /* if tx get ac, ax, be mode, need not get mode from rx */
8050 if (strncmp(temp[i].cli_OperatingStandard,"ac", 2) &&
8051 strncmp(temp[i].cli_OperatingStandard,"ax", 2) &&
8052 strncmp(temp[i].cli_OperatingStandard,"be", 2)) {
8053 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8054 if (ret == RETURN_ERR) {
8055 wifi_dbg_printf("%s: failed to execute rx get assoc connect mode command.\n", __FUNCTION__);
8056 return ret;
8057 }
8058 }
8059 }
developer06a01d92022-09-07 16:32:39 +08008060 // Here other fields can be parsed if added to filter of 'iw dev' command
developer06a01d92022-09-07 16:32:39 +08008061 ptr = get_line_from_str_buf(ptr, line);
developer9a9f46e2023-11-09 09:22:42 +08008062 }
developer06a01d92022-09-07 16:32:39 +08008063
8064 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008065 return RETURN_OK;
8066}
8067
8068#if 0
8069//To-do
8070INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8071{
8072 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8073
8074 //Using different approach to get required WiFi Parameters from system available commands
8075#if 0
8076 FILE *f;
8077 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8078 char cmd[256], buf[2048];
8079 char *param , *value, *line=NULL;
8080 size_t len = 0;
8081 ssize_t nread;
8082 wifi_associated_dev3_t *dev=NULL;
8083 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08008084 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08008085 _syscmd(cmd,buf,sizeof(buf));
8086 *output_array_size = atoi(buf);
8087
8088 if (*output_array_size <= 0)
8089 return RETURN_OK;
8090
8091 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8092 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08008093 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08008094 _syscmd(cmd,buf,sizeof(buf));
8095 f = fopen("/tmp/connected_devices.txt", "r");
8096 if (f==NULL)
8097 {
8098 *output_array_size=0;
8099 return RETURN_ERR;
8100 }
8101 while ((nread = getline(&line, &len, f)) != -1)
8102 {
8103 param = strtok(line,"=");
8104 value = strtok(NULL,"=");
8105
8106 if( strcmp("flags",param) == 0 )
8107 {
8108 value[strlen(value)-1]='\0';
8109 if(strstr (value,"AUTHORIZED") != NULL )
8110 {
8111 dev[auth_temp].cli_AuthenticationState = 1;
8112 dev[auth_temp].cli_Active = 1;
8113 auth_temp++;
8114 read_flag=1;
8115 }
8116 }
8117 if(read_flag==1)
8118 {
8119 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8120 {
8121 value[strlen(value)-1]='\0';
8122 sscanf(value, "%x:%x:%x:%x:%x:%x",
8123 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8124 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8125 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8126 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8127 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8128 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8129
8130 }
8131 else if( strcmp("rx_packets",param) == 0 )
8132 {
8133 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8134 }
8135
8136 else if( strcmp("tx_packets",param) == 0 )
8137 {
8138 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8139 }
8140
8141 else if( strcmp("rx_bytes",param) == 0 )
8142 {
8143 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8144 }
8145
8146 else if( strcmp("tx_bytes",param) == 0 )
8147 {
8148 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8149 mac_temp++;
8150 read_flag=0;
8151 }
8152 }
8153 }
8154
8155 *output_array_size = auth_temp;
8156 auth_temp=0;
8157 mac_temp=0;
8158 free(line);
8159 fclose(f);
8160#endif
8161 char interface_name[MAX_BUF_SIZE] = {0};
8162 char wifi_status[MAX_BUF_SIZE] = {0};
8163 char hostapdconf[MAX_BUF_SIZE] = {0};
8164
8165 wifi_associated_dev3_t *dev_array = NULL;
8166 ULONG wifi_count = 0;
8167
8168 *associated_dev_array = NULL;
8169 *output_array_size = 0;
8170
8171 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8172 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8173 {
8174 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8175
developerac6f1142022-12-20 19:26:35 +08008176 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008177
8178 if(strlen(interface_name) > 1)
8179 {
8180 wifihal_interfacestatus(wifi_status,interface_name);
8181 if(strcmp(wifi_status,"RUNNING") == 0)
8182 {
8183 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8184
8185 *associated_dev_array = dev_array;
8186 *output_array_size = wifi_count;
8187 }
8188 else
8189 {
8190 *associated_dev_array = NULL;
8191 }
8192 }
8193 }
8194
8195 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8196 return RETURN_OK;
8197}
8198#endif
8199
8200/* getIPAddress function */
8201/**
8202* @description Returning IpAddress of the Matched String
8203*
8204* @param
8205* @str Having MacAddress
8206* @ipaddr Having ipaddr
8207* @return The status of the operation
8208* @retval RETURN_OK if successful
8209* @retval RETURN_ERR if any error is detected
8210*
8211*/
8212
8213INT getIPAddress(char *str,char *ipaddr)
8214{
8215 FILE *fp = NULL;
8216 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8217 int LeaseTime = 0,ret = 0;
8218 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8219 {
8220 return RETURN_ERR;
8221 }
8222
8223 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8224 {
8225 /*
8226 Sample:sss
8227 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8228 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8229 */
8230 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008231 &(LeaseTime),
8232 phyAddr,
8233 ipAddr,
8234 hostName
8235 );
developer06a01d92022-09-07 16:32:39 +08008236 if(ret != 4)
8237 continue;
8238 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008239 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008240 }
developerd946fd62022-12-08 18:03:28 +08008241 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008242 return RETURN_OK;
8243}
8244
8245/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8246/**
8247* @description Returning Inactive wireless connected clients informations
8248*
8249* @param
8250* @filename Holding private_wifi 2g/5g content files
8251* @associated_dev_array Having inactiv wireless clients informations
8252* @output_array_size Returning Inactive wireless counts
8253* @return The status of the operation
8254* @retval RETURN_OK if successful
8255* @retval RETURN_ERR if any error is detected
8256*
8257*/
8258
8259INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8260{
8261 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8262 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8263 FILE *fp = NULL;
8264 int arr[MACADDRESS_SIZE] = {0};
8265 unsigned char mac[MACADDRESS_SIZE] = {0};
8266 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8267 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8268 fp = popen(buf,"r");
8269 if(fp == NULL)
8270 return RETURN_ERR;
8271 else
8272 {
8273 fgets(path,sizeof(path),fp);
8274 maccount = atoi(path);
8275 }
8276 pclose(fp);
8277 *output_array_size = maccount;
8278 wifi_associated_dev3_t* temp = NULL;
8279 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8280 *associated_dev_array = temp;
8281 if(temp == NULL)
8282 {
8283 printf("Error Statement. Insufficient memory \n");
8284 return RETURN_ERR;
8285 }
8286 memset(buf,0,sizeof(buf));
8287 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8288 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008289 if (fp == NULL) {
8290 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8291 return RETURN_ERR;
8292 }
developer06a01d92022-09-07 16:32:39 +08008293 for(count = 0; count < maccount ; count++)
8294 {
8295 fgets(path,sizeof(path),fp);
8296 for(i = 0; path[i]!='\n';i++)
8297 str[i]=path[i];
8298 str[i]='\0';
8299 getIPAddress(str,ipaddr);
8300 memset(buf,0,sizeof(buf));
8301 if(strlen(ipaddr) > 0)
8302 {
8303 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8304 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8305 {
8306 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8307 {
8308 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8309 {
8310 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8311
8312 }
8313 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8314 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]);
8315 }
8316 temp[count].cli_AuthenticationState = 0; //TODO
8317 temp[count].cli_Active = 0; //TODO
8318 temp[count].cli_SignalStrength = 0;
8319 }
8320 else //Active wireless clients info
8321 {
8322 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8323 {
8324 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8325 {
8326 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8327
8328 }
8329 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8330 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]);
8331 }
8332 temp[count].cli_Active = 1;
8333 }
8334 }
8335 memset(ipaddr,0,sizeof(ipaddr));
8336 }
8337 pclose(fp);
8338 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8339 return RETURN_OK;
8340}
8341//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8342//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8343//To get Band Steering Capability
8344INT wifi_getBandSteeringCapability(BOOL *support)
8345{
8346 *support = FALSE;
8347 return RETURN_OK;
8348}
8349
8350
8351//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8352//To get Band Steering enable status
8353INT wifi_getBandSteeringEnable(BOOL *enable)
8354{
8355 *enable = FALSE;
8356 return RETURN_OK;
8357}
8358
8359//To turn on/off Band steering
8360INT wifi_setBandSteeringEnable(BOOL enable)
8361{
8362 return RETURN_OK;
8363}
8364
8365//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8366//To get Band Steering AP group
8367INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8368{
8369 if (NULL == output_ApGroup)
8370 return RETURN_ERR;
8371
8372 strcpy(output_ApGroup, "1,2");
8373 return RETURN_OK;
8374}
8375
8376//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8377//to set and read the band steering BandUtilizationThreshold parameters
8378INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8379{
8380 return RETURN_ERR;
8381}
8382
8383INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8384{
8385 return RETURN_ERR;
8386}
8387
8388//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8389//to set and read the band steering RSSIThreshold parameters
8390INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8391{
8392 return RETURN_ERR;
8393}
8394
8395INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8396{
8397 return RETURN_ERR;
8398}
8399
8400
8401//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8402//to set and read the band steering physical modulation rate threshold parameters
8403INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8404{
8405 //If chip is not support, return -1
8406 return RETURN_ERR;
8407}
8408
8409INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8410{
8411 //If chip is not support, return -1
8412 return RETURN_ERR;
8413}
8414
8415//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8416//to set and read the inactivity time (in seconds) for steering under overload condition
8417INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8418{
8419 return RETURN_ERR;
8420}
8421
8422INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8423{
8424 return RETURN_ERR;
8425}
8426
8427//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8428//to set and read the inactivity time (in seconds) for steering under Idle condition
8429INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8430{
8431 return RETURN_ERR;
8432}
8433
8434INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8435{
8436 return RETURN_ERR;
8437}
8438
8439//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8440//pClientMAC[64]
8441//pSourceSSIDIndex[64]
8442//pDestSSIDIndex[64]
8443//pSteeringReason[256]
8444INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8445{
8446 //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
8447 *pSteeringTime=time(NULL);
8448 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8449 return RETURN_OK;
8450}
8451
8452INT wifi_ifConfigDown(INT apIndex)
8453{
8454 INT status = RETURN_OK;
8455 char cmd[64];
8456
8457 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8458 printf("%s: %s\n", __func__, cmd);
8459 system(cmd);
8460
8461 return status;
8462}
8463
8464INT wifi_ifConfigUp(INT apIndex)
8465{
developerd946fd62022-12-08 18:03:28 +08008466 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008467 char cmd[128];
8468 char buf[1024];
8469
developerac6f1142022-12-20 19:26:35 +08008470 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008471 return RETURN_ERR;
8472 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008473 _syscmd(cmd, buf, sizeof(buf));
8474 return 0;
8475}
8476
8477//>> Deprecated. Replace with wifi_applyRadioSettings
8478INT wifi_pushBridgeInfo(INT apIndex)
8479{
developerd946fd62022-12-08 18:03:28 +08008480 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008481 char ip[32] = {0};
8482 char subnet[32] = {0};
8483 char bridge[32] = {0};
8484 int vlanId = 0;
8485 char cmd[128] = {0};
8486 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008487
8488 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8489 wifi_getApVlanID(apIndex,&vlanId);
8490
developerac6f1142022-12-20 19:26:35 +08008491 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008492 return RETURN_ERR;
8493 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008494 _syscmd(cmd,buf, sizeof(buf));
8495
8496 return 0;
8497}
8498
8499INT wifi_pushChannel(INT radioIndex, UINT channel)
8500{
developerd946fd62022-12-08 18:03:28 +08008501 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008502 char cmd[128];
8503 char buf[1024];
8504 int apIndex;
8505
8506 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008507 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008508 return RETURN_ERR;
8509 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008510 _syscmd(cmd,buf, sizeof(buf));
8511
8512 return 0;
8513}
8514
8515INT wifi_pushChannelMode(INT radioIndex)
8516{
8517 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8518 return RETURN_ERR;
8519}
8520
8521INT wifi_pushDefaultValues(INT radioIndex)
8522{
8523 //Apply Comcast specified default radio settings instantly
8524 //AMPDU=1
8525 //AMPDUFrames=32
8526 //AMPDULim=50000
8527 //txqueuelen=1000
8528
8529 return RETURN_ERR;
8530}
8531
8532INT wifi_pushTxChainMask(INT radioIndex)
8533{
8534 //Apply default TxChainMask instantly
8535 return RETURN_ERR;
8536}
8537
8538INT wifi_pushRxChainMask(INT radioIndex)
8539{
8540 //Apply default RxChainMask instantly
8541 return RETURN_ERR;
8542}
8543
8544INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8545{
8546 INT status;
8547
8548 status = wifi_setSSIDName(apIndex,ssid);
8549 wifi_setApEnable(apIndex,FALSE);
8550 wifi_setApEnable(apIndex,TRUE);
8551
8552 return status;
8553}
8554
8555INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8556{
8557 //Apply default Ssid Advertisement instantly
8558 return RETURN_ERR;
8559}
8560
8561INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8562{
8563 INT status = RETURN_ERR;
8564 *output = 0;
8565 return RETURN_ERR;
8566}
8567
8568INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8569{
8570 return RETURN_OK;
8571}
8572
8573INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8574{
8575 return RETURN_OK;
8576}
8577
8578//To-do
8579INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8580{
developereb199ae2022-09-13 14:04:27 +08008581 char output[16]={'\0'};
8582 char config_file[MAX_BUF_SIZE] = {0};
8583
8584 if (!output_string)
8585 return RETURN_ERR;
8586
8587 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8588 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8589
8590 if (strlen(output) == 0)
8591 snprintf(output_string, 64, "Disabled");
8592 else if (strncmp(output, "0", 1) == 0)
8593 snprintf(output_string, 64, "Disabled");
8594 else if (strncmp(output, "1", 1) == 0)
8595 snprintf(output_string, 64, "Optional");
8596 else if (strncmp(output, "2", 1) == 0)
8597 snprintf(output_string, 64, "Required");
8598 else {
8599 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8600 return RETURN_ERR;
8601 }
8602
8603 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008604 return RETURN_OK;
8605}
8606INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8607{
developereb199ae2022-09-13 14:04:27 +08008608 char str[MAX_BUF_SIZE]={'\0'};
8609 char cmd[MAX_CMD_SIZE]={'\0'};
8610 struct params params;
8611 char config_file[MAX_BUF_SIZE] = {0};
8612
8613 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8614 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8615 return RETURN_ERR;
8616
8617 params.name = "ieee80211w";
8618 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8619 params.value = "0";
8620 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8621 params.value = "1";
8622 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8623 params.value = "2";
8624 else{
8625 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8626 return RETURN_ERR;
8627 }
8628 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8629 wifi_hostapdWrite(config_file, &params, 1);
8630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008631 return RETURN_OK;
8632}
8633INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8634{
8635 char output[16]={'\0'};
8636 char config_file[MAX_BUF_SIZE] = {0};
8637
8638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8639 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8640 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8641
8642 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8643 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8644
8645 return RETURN_OK;
8646}
8647
8648INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8649{
8650 return RETURN_OK;
8651}
8652
8653INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8654{
8655 return RETURN_OK;
8656}
8657
8658INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8659{
8660 return RETURN_OK;
8661}
8662
8663INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8664{
8665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8666 char config_file[MAX_BUF_SIZE] = {0};
8667
8668 if (NULL == output)
8669 return RETURN_ERR;
8670 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8671 wifi_hostapdRead(config_file,"hw_mode",output,64);
8672
8673 if(strcmp(output,"b")==0)
8674 sprintf(output, "%s", "1,2,5.5,11");
8675 else if (strcmp(output,"a")==0)
8676 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8677 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8678 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8679
8680 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8681 return RETURN_OK;
8682}
8683
8684INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8685{
8686 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8687 char *temp;
8688 char temp_output[128];
8689 char temp_TransmitRates[128];
8690 char config_file[MAX_BUF_SIZE] = {0};
8691
8692 if (NULL == output)
8693 return RETURN_ERR;
8694
8695 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8696 wifi_hostapdRead(config_file,"supported_rates",output,64);
8697
developer5b398df2022-11-17 20:39:48 +08008698 if (strlen(output) == 0) {
8699 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8700 return RETURN_OK;
8701 }
developer06a01d92022-09-07 16:32:39 +08008702 strcpy(temp_TransmitRates,output);
8703 strcpy(temp_output,"");
8704 temp = strtok(temp_TransmitRates," ");
8705 while(temp!=NULL)
8706 {
8707 temp[strlen(temp)-1]=0;
8708 if((temp[0]=='5') && (temp[1]=='\0'))
8709 {
8710 temp="5.5";
8711 }
8712 strcat(temp_output,temp);
8713 temp = strtok(NULL," ");
8714 if(temp!=NULL)
8715 {
8716 strcat(temp_output,",");
8717 }
8718 }
8719 strcpy(output,temp_output);
8720 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8721
8722 return RETURN_OK;
8723}
8724
8725INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8726{
8727 return RETURN_OK;
8728}
8729
8730
8731INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8732{
8733 int i=0;
8734 char *temp;
developeref938762022-10-19 17:21:01 +08008735 char temp1[128] = {0};
8736 char temp_output[128] = {0};
8737 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008738 struct params params={'\0'};
8739 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008740 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008741
8742 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8743 if(NULL == output)
8744 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008745 strcpy(temp_TransmitRates,output);
8746
8747 for(i=0;i<strlen(temp_TransmitRates);i++)
8748 {
developeref938762022-10-19 17:21:01 +08008749 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008750 {
8751 continue;
8752 }
8753 else
8754 {
8755 return RETURN_ERR;
8756 }
8757 }
8758 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008759 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008760 while(temp!=NULL)
8761 {
8762 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008763 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008764 {
developeref938762022-10-19 17:21:01 +08008765 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008766 {
8767 return RETURN_ERR;
8768 }
8769 }
8770
8771 if(strcmp(temp,"5.5")==0)
8772 {
8773 strcpy(temp1,"55");
8774 }
8775 else
8776 {
8777 strcat(temp1,"0");
8778 }
8779 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008780 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008781 if(temp!=NULL)
8782 {
8783 strcat(temp_output," ");
8784 }
8785 }
8786 strcpy(output,temp_output);
8787
developer06a01d92022-09-07 16:32:39 +08008788 params.name = "supported_rates";
8789 params.value = output;
8790
8791 wifi_dbg_printf("\n%s:",__func__);
8792 wifi_dbg_printf("params.value=%s\n",params.value);
8793 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8794 wifi_hostapdWrite(config_file,&params,1);
8795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8796
8797 return RETURN_OK;
8798}
8799
8800
8801static char *sncopy(char *dst, int dst_sz, const char *src)
8802{
8803 if (src && dst && dst_sz > 0) {
8804 strncpy(dst, src, dst_sz);
8805 dst[dst_sz - 1] = '\0';
8806 }
8807 return dst;
8808}
8809
8810static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8811{
8812 if (0 == strcmp(ht_mode, "HT40") ||
8813 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008814 0 == strcmp(ht_mode, "HT160") ||
8815 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008816 switch (channel) {
developer9a520b12023-09-21 16:01:43 +08008817 case 0 ... 7:
developer06a01d92022-09-07 16:32:39 +08008818 case 36:
8819 case 44:
8820 case 52:
8821 case 60:
8822 case 100:
8823 case 108:
8824 case 116:
8825 case 124:
8826 case 132:
8827 case 140:
8828 case 149:
8829 case 157:
8830 return 1;
8831 case 8 ... 13:
8832 case 40:
8833 case 48:
8834 case 56:
8835 case 64:
8836 case 104:
8837 case 112:
8838 case 120:
8839 case 128:
8840 case 136:
8841 case 144:
8842 case 153:
8843 case 161:
8844 return -1;
8845 default:
8846 return -EINVAL;
8847 }
8848 }
8849
8850 return -EINVAL;
8851}
8852
developerb7593de2022-10-18 09:51:57 +08008853static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8854{
8855 int idx = channel%8;
8856 if (0 == strcmp(ht_mode, "HT40") ||
8857 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008858 0 == strcmp(ht_mode, "HT160") ||
8859 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008860 switch (idx) {
8861 case 1:
8862 return 1;
8863 case 5:
8864 return -1;
8865 default:
8866 return -EINVAL;
8867 }
8868 }
8869
8870 return -EINVAL;
8871}
developer06a01d92022-09-07 16:32:39 +08008872static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8873{
8874 if (NULL == hw_mode) return;
8875
8876 if (0 == strcmp(hw_mode, "ac"))
8877 sncopy(bw_mode, bw_mode_len, "ht vht");
8878
8879 if (0 == strcmp(hw_mode, "n"))
8880 sncopy(bw_mode, bw_mode_len, "ht");
8881
8882 return;
8883}
8884
8885static int util_chan_to_freq(int chan)
8886{
8887 if (chan == 14)
8888 return 2484;
8889 else if (chan < 14)
8890 return 2407 + chan * 5;
8891 else if (chan >= 182 && chan <= 196)
8892 return 4000 + chan * 5;
8893 else
8894 return 5000 + chan * 5;
8895 return 0;
8896}
8897
developerb7593de2022-10-18 09:51:57 +08008898static int util_6G_chan_to_freq(int chan)
8899{
8900 if (chan)
8901 return 5950 + chan * 5;
8902 else
8903 return 0;
8904
8905}
developer06a01d92022-09-07 16:32:39 +08008906const int *util_unii_5g_chan2list(int chan, int width)
8907{
8908 static const int lists[] = {
8909 // <width>, <chan1>, <chan2>..., 0,
developer8b2f01f2024-03-01 14:50:27 +08008910 20, 36, 0,
8911 20, 40, 0,
8912 20, 44, 0,
8913 20, 48, 0,
8914 20, 52, 0,
8915 20, 56, 0,
8916 20, 60, 0,
8917 20, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008918 20, 100, 0,
8919 20, 104, 0,
8920 20, 108, 0,
8921 20, 112, 0,
8922 20, 116, 0,
8923 20, 120, 0,
8924 20, 124, 0,
8925 20, 128, 0,
8926 20, 132, 0,
8927 20, 136, 0,
8928 20, 140, 0,
8929 20, 144, 0,
8930 20, 149, 0,
8931 20, 153, 0,
8932 20, 157, 0,
8933 20, 161, 0,
8934 20, 165, 0,
developer8b2f01f2024-03-01 14:50:27 +08008935 20, 169, 0,
8936 20, 173, 0,
8937 20, 177, 0,
8938 40, 36, 40, 0,
8939 40, 44, 48, 0,
8940 40, 52, 56, 0,
8941 40, 60, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008942 40, 100, 104, 0,
8943 40, 108, 112, 0,
8944 40, 116, 120, 0,
8945 40, 124, 128, 0,
8946 40, 132, 136, 0,
8947 40, 140, 144, 0,
8948 40, 149, 153, 0,
8949 40, 157, 161, 0,
developer8b2f01f2024-03-01 14:50:27 +08008950 40, 165, 169, 0,
8951 40, 173, 177, 0,
8952 80, 36, 40, 44, 48, 0,
8953 80, 52, 56, 60, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008954 80, 100, 104, 108, 112, 0,
8955 80, 116, 120, 124, 128, 0,
8956 80, 132, 136, 140, 144, 0,
8957 80, 149, 153, 157, 161, 0,
developer8b2f01f2024-03-01 14:50:27 +08008958 80, 165, 169, 173, 177, 0,
8959 160,36, 40, 44, 48, 52, 56, 60, 64, 0,
8960 160,100, 104, 108, 112, 116, 120, 124, 128, 0,
8961 160,149, 153, 157, 161, 165, 169, 173, 177, 0,
developer06a01d92022-09-07 16:32:39 +08008962 -1 // final delimiter
8963 };
8964 const int *start;
8965 const int *p;
8966
8967 for (p = lists; *p != -1; p++) {
8968 if (*p == width) {
8969 for (start = ++p; *p != 0; p++) {
8970 if (*p == chan)
8971 return start;
8972 }
8973 }
8974 // move to the end of channel list of given width
8975 while (*p != 0) {
8976 p++;
8977 }
8978 }
8979
8980 return NULL;
8981}
8982
8983static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8984{
8985 if (NULL == ht_mode)
8986 return 0;
8987
8988 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8989 const int *chans = util_unii_5g_chan2list(channel, width);
8990 int sum = 0;
8991 int cnt = 0;
8992
8993 if (NULL == chans)
8994 return 0;
8995
8996 while (*chans) {
8997 sum += *chans;
8998 cnt++;
8999 chans++;
9000 }
developer30423732022-12-01 16:17:49 +08009001 if (cnt == 0)
9002 return 0;
developer06a01d92022-09-07 16:32:39 +08009003 return sum / cnt;
9004}
9005
developerb7593de2022-10-18 09:51:57 +08009006static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
9007{
9008 if (NULL == ht_mode)
9009 return 0;
9010
9011 int width = strtol((ht_mode + 2), NULL, 10);
9012
9013 int idx = 0 ;
9014 int centerchan = 0;
9015 int chan_ofs = 1;
9016
9017 if (width == 40){
9018 idx = ((channel/4) + chan_ofs)%2;
9019 switch (idx) {
9020 case 0:
9021 centerchan = (channel - 2);
9022 break;
9023 case 1:
9024 centerchan = (channel + 2);
9025 break;
9026 default:
9027 return -EINVAL;
9028 }
9029 }else if (width == 80){
9030 idx = ((channel/4) + chan_ofs)%4;
9031 switch (idx) {
9032 case 0:
9033 centerchan = (channel - 6);
9034 break;
9035 case 1:
9036 centerchan = (channel + 6);
9037 break;
9038 case 2:
9039 centerchan = (channel + 2);
9040 break;
9041 case 3:
9042 centerchan = (channel - 2);
9043 break;
9044 default:
9045 return -EINVAL;
9046 }
9047 }else if (width == 160){
9048 switch (channel) {
9049 case 1 ... 29:
9050 centerchan = 15;
9051 break;
9052 case 33 ... 61:
9053 centerchan = 47;
9054 break;
9055 case 65 ... 93:
9056 centerchan = 79;
9057 break;
9058 case 97 ... 125:
9059 centerchan = 111;
9060 break;
9061 case 129 ... 157:
9062 centerchan = 143;
9063 break;
9064 case 161 ... 189:
9065 centerchan = 175;
9066 break;
9067 case 193 ... 221:
9068 centerchan = 207;
9069 break;
9070 default:
9071 return -EINVAL;
9072 }
developer7c4cd202023-03-01 10:56:29 +08009073 }else if (width == 320){
9074 switch (channel) {
9075 case 1 ... 29:
9076 centerchan = 31;
9077 break;
9078 case 33 ... 93:
9079 centerchan = 63;
9080 break;
9081 case 97 ... 157:
9082 centerchan = 127;
9083 break;
9084 case 161 ... 221:
9085 centerchan = 191;
9086 break;
9087 default:
9088 return -EINVAL;
9089 }
developerb7593de2022-10-18 09:51:57 +08009090 }
9091 return centerchan;
9092}
developer06a01d92022-09-07 16:32:39 +08009093static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9094{
9095 BOOL onlyG, onlyN, onlyA;
9096 CHAR tmp[64];
9097 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9098 if (ret == RETURN_OK) {
9099 sncopy(hw_mode, hw_mode_size, tmp);
9100 }
9101 return ret;
9102}
9103
9104INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9105{
9106 // Sample commands:
9107 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9108 // hostapd_cli -i wifi0 chan_switch 30 2437
9109 char cmd[MAX_CMD_SIZE] = {0};
9110 char buf[MAX_BUF_SIZE] = {0};
9111 int freq = 0, ret = 0;
9112 char center_freq1_str[32] = ""; // center_freq1=%d
9113 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9114 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9115 char hw_mode[16] = ""; // n|ac
9116 char bw_mode[16] = ""; // ht|ht vht
9117 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08009118 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009119 int sec_chan_offset;
9120 int width;
developer4fb0b922022-09-30 14:29:09 +08009121 char config_file[64] = {0};
9122 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08009123 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08009124 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08009125 wifi_band band = band_invalid;
9126 int center_chan = 0;
9127 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08009128
developer4fb0b922022-09-30 14:29:09 +08009129 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08009130
developerac6f1142022-12-20 19:26:35 +08009131 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009132 return RETURN_ERR;
9133
developer06a01d92022-09-07 16:32:39 +08009134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9135
developerb7593de2022-10-18 09:51:57 +08009136 band = wifi_index_to_band(radioIndex);
9137
developer5884e982022-10-06 10:52:50 +08009138 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08009139
9140 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08009141 if (channel){
developerb7593de2022-10-18 09:51:57 +08009142 if (band == band_6){
9143 freq = util_6G_chan_to_freq(channel);
9144 }else{
9145 freq = util_chan_to_freq(channel);
9146 }
developer7c4cd202023-03-01 10:56:29 +08009147 if (width == 320) {
9148 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
9149 setEHT320 = TRUE;
9150 }
developer5884e982022-10-06 10:52:50 +08009151 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08009152
developer5884e982022-10-06 10:52:50 +08009153 // Provide bandwith if specified
9154 if (channel_width_MHz > 20) {
9155 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9156 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9157 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08009158
developer5884e982022-10-06 10:52:50 +08009159 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9160 }else if (channel_width_MHz == 20){
9161 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9162 }
developer06a01d92022-09-07 16:32:39 +08009163
developerb7593de2022-10-18 09:51:57 +08009164
developer5884e982022-10-06 10:52:50 +08009165 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08009166 if (band == band_6){
9167 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9168 if(center_chan){
9169 center_freq1 = util_6G_chan_to_freq(center_chan);
9170 }
9171 }else{
9172 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9173 if(center_chan){
9174 center_freq1 = util_chan_to_freq(center_chan);
9175 }
developer5884e982022-10-06 10:52:50 +08009176 }
developerb7593de2022-10-18 09:51:57 +08009177
9178 if (center_freq1)
9179 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9180
9181 }
9182
9183 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9184 if (band == band_6){
9185 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9186 }else{
9187 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009188 }
developerb7593de2022-10-18 09:51:57 +08009189 if (sec_chan_offset != -EINVAL)
9190 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009191
developer5884e982022-10-06 10:52:50 +08009192 // Only the first AP, other are hanging on the same radio
9193 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009194 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9195 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009196 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9197 wifi_dbg_printf("execute: '%s'\n", cmd);
9198 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009199 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009200
developer5884e982022-10-06 10:52:50 +08009201 ret = wifi_setRadioChannel(radioIndex, channel);
9202 if (ret != RETURN_OK) {
9203 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9204 return RETURN_ERR;
9205 }
9206
9207 if (sec_chan_offset == 1) ext_str = "Above";
9208 else if (sec_chan_offset == -1) ext_str = "Below";
9209
9210 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009211
developer5884e982022-10-06 10:52:50 +08009212 } else {
9213 if (channel_width_MHz > 20)
9214 ext_str = "Above";
9215 }
developer4fb0b922022-09-30 14:29:09 +08009216
developer06a01d92022-09-07 16:32:39 +08009217 char mhz_str[16];
9218 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009219 if (setEHT320 == TRUE)
9220 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9221 else
9222 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009223
developer57fa24a2023-03-15 17:25:07 +08009224 writeBandWidth(radioIndex, mhz_str);
9225 if (band == band_2_4 || band == band_5) {
9226 if (width == 20)
9227 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9228 else
9229 wifi_setRadioExtChannel(radioIndex, ext_str);
9230 }
developer06a01d92022-09-07 16:32:39 +08009231 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9232
9233 return RETURN_OK;
9234}
9235
9236INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9237{
developer615510b2022-09-27 10:14:35 +08009238 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009239 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009240 char cmd[256]={0};
9241 char buf[128]={0};
9242 char file_name[32] = {0};
9243 char filter_SSID[32] = {0};
9244 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009245 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009246 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009247 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009248 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009249 size_t len=0;
9250 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009251 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009252 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009253 bool filter_enable = false;
9254 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009255 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009256
developer615510b2022-09-27 10:14:35 +08009257 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009258
developer615510b2022-09-27 10:14:35 +08009259 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9260 f = fopen(file_name, "r");
9261 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009262 fgets(buf, sizeof(file_name), f);
9263 if ((strncmp(buf, "0", 1)) != 0) {
9264 fgets(filter_SSID, sizeof(file_name), f);
9265 if (strlen(filter_SSID) != 0)
9266 filter_enable = true;
9267 }
developer615510b2022-09-27 10:14:35 +08009268 fclose(f);
9269 }
9270
developerac6f1142022-12-20 19:26:35 +08009271 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009272 return RETURN_ERR;
9273
developer033b37b2022-10-18 11:27:46 +08009274 phyId = radio_index_to_phy(radio_index);
9275
9276 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009277 _syscmd(cmd, buf, sizeof(buf));
9278 channels_num = strtol(buf, NULL, 10);
9279
developerd946fd62022-12-08 18:03:28 +08009280 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9281 // 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 +08009282 fprintf(stderr, "cmd: %s\n", cmd);
9283 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009284 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9285 return RETURN_ERR;
9286 }
developer5550e242022-09-30 09:59:32 +08009287
9288 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9289 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9290
developer615510b2022-09-27 10:14:35 +08009291 ret = fgets(line, sizeof(line), f);
9292 while (ret != NULL) {
9293 if(strstr(line, "BSS") != NULL) { // new neighbor info
9294 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9295 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9296 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9297
9298 if (!filter_BSS) {
9299 index++;
9300 wifi_neighbor_ap2_t *tmp;
9301 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9302 if (tmp == NULL) { // no more memory to use
9303 index--;
9304 wifi_dbg_printf("%s: realloc failed\n", __func__);
9305 break;
9306 }
9307 scan_array = tmp;
9308 }
9309 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009310
developer615510b2022-09-27 10:14:35 +08009311 filter_BSS = false;
9312 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9313 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9314 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9315 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9316 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009317 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009318 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009319
developer615510b2022-09-27 10:14:35 +08009320 if (freq >= 2412 && freq <= 2484) {
9321 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9322 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9323 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9324 }
9325 else if (freq >= 5160 && freq <= 5805) {
9326 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9327 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9328 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9329 }
developer06a01d92022-09-07 16:32:39 +08009330
developer615510b2022-09-27 10:14:35 +08009331 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009332 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009333 for (int i = 0; i < channels_num; i++) {
9334 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9335 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9336 break;
9337 }
9338 }
developer06a01d92022-09-07 16:32:39 +08009339 }
developer615510b2022-09-27 10:14:35 +08009340 } else if (strstr(line, "beacon interval") != NULL) {
9341 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9342 } else if (strstr(line, "signal") != NULL) {
9343 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9344 } else if (strstr(line,"SSID") != NULL) {
9345 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9346 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9347 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009348 }
developer615510b2022-09-27 10:14:35 +08009349 } else if (strstr(line, "Supported rates") != NULL) {
9350 char SRate[80] = {0}, *tmp = NULL;
9351 memset(buf, 0, sizeof(buf));
9352 strcpy(SRate, line);
9353 tmp = strtok(SRate, ":");
9354 tmp = strtok(NULL, ":");
9355 strcpy(buf, tmp);
9356 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009357
developer615510b2022-09-27 10:14:35 +08009358 tmp = strtok(buf, " \n");
9359 while (tmp != NULL) {
9360 strcat(SRate, tmp);
9361 if (SRate[strlen(SRate) - 1] == '*') {
9362 SRate[strlen(SRate) - 1] = '\0';
9363 }
9364 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009365
developer615510b2022-09-27 10:14:35 +08009366 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009367 }
developer615510b2022-09-27 10:14:35 +08009368 SRate[strlen(SRate) - 1] = '\0';
9369 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9370 } else if (strstr(line, "DTIM") != NULL) {
9371 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9372 } else if (strstr(line, "VHT capabilities") != NULL) {
9373 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9374 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9375 } else if (strstr(line, "HT capabilities") != NULL) {
9376 strcat(scan_array[index].ap_SupportedStandards, ",n");
9377 strcpy(scan_array[index].ap_OperatingStandards, "n");
9378 } else if (strstr(line, "VHT operation") != NULL) {
9379 ret = fgets(line, sizeof(line), f);
9380 sscanf(line," * channel width: %d", &vht_channel_width);
9381 if(vht_channel_width == 1) {
9382 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9383 } else {
9384 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9385 }
9386 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9387 continue;
9388 } else if (strstr(line, "HT operation") != NULL) {
9389 ret = fgets(line, sizeof(line), f);
9390 sscanf(line," * secondary channel offset: %s", &buf);
9391 if (!strcmp(buf, "above")) {
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_HT40PLUS", radio_index%1 ? "A": "G");
developer06a01d92022-09-07 16:32:39 +08009394 }
developer615510b2022-09-27 10:14:35 +08009395 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009396 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009397 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9398 } else {
9399 //20Mhz
9400 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 +08009401 }
developer615510b2022-09-27 10:14:35 +08009402 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009403 continue;
developer615510b2022-09-27 10:14:35 +08009404 } else if (strstr(line, "HE capabilities") != NULL) {
9405 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9406 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9407 ret = fgets(line, sizeof(line), f);
9408 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9409 if (strstr(line, "HE40/2.4GHz") != NULL)
9410 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9411 else
9412 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9413 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9414 if (strstr(line, "HE80/5GHz") != NULL) {
9415 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9416 ret = fgets(line, sizeof(line), f);
9417 } else
9418 continue;
9419 if (strstr(line, "HE160/5GHz") != NULL)
9420 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009421 }
developer615510b2022-09-27 10:14:35 +08009422 continue;
9423 } else if (strstr(line, "WPA") != NULL) {
9424 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9425 } else if (strstr(line, "RSN") != NULL) {
9426 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9427 } else if (strstr(line, "Group cipher") != NULL) {
9428 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9429 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9430 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009431 }
developer06a01d92022-09-07 16:32:39 +08009432 }
developer615510b2022-09-27 10:14:35 +08009433 ret = fgets(line, sizeof(line), f);
9434 }
9435
9436 if (!filter_BSS) {
9437 *output_array_size = index + 1;
9438 } else {
9439 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9440 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009441 }
developer06a01d92022-09-07 16:32:39 +08009442 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009443 pclose(f);
developer5550e242022-09-30 09:59:32 +08009444 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009445 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009446 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009447}
developer615510b2022-09-27 10:14:35 +08009448
developer06a01d92022-09-07 16:32:39 +08009449INT wifi_getApAssociatedDeviceStats(
9450 INT apIndex,
9451 mac_address_t *clientMacAddress,
9452 wifi_associated_dev_stats_t *associated_dev_stats,
9453 u64 *handle)
9454{
9455 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9456 char interface_name[50] = {0};
9457 char cmd[1024] = {0};
9458 char mac_str[18] = {0};
9459 char *key = NULL;
9460 char *val = NULL;
9461 FILE *f = NULL;
9462 char *line = NULL;
9463 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009464
9465 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9466 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9467 return RETURN_ERR;
9468 }
9469
9470 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9471 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9472 if((f = popen(cmd, "r")) == NULL) {
9473 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9474 return RETURN_ERR;
9475 }
9476
developer30423732022-12-01 16:17:49 +08009477 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009478 key = strtok(line,":");
9479 val = strtok(NULL,":");
9480
9481 if(!strncmp(key,"rx bytes",8))
9482 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9483 if(!strncmp(key,"tx bytes",8))
9484 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9485 if(!strncmp(key,"rx packets",10))
9486 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9487 if(!strncmp(key,"tx packets",10))
9488 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9489 if(!strncmp(key,"tx retries",10))
9490 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9491 if(!strncmp(key,"tx failed",9))
9492 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9493 if(!strncmp(key,"rx drop misc",13))
9494 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9495 if(!strncmp(key,"rx bitrate",10)) {
9496 val = strtok(val, " ");
9497 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9498 }
9499 if(!strncmp(key,"tx bitrate",10)) {
9500 val = strtok(val, " ");
9501 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9502 }
9503 }
9504 free(line);
9505 pclose(f);
9506 return RETURN_OK;
9507}
9508
9509INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9510{
developerd946fd62022-12-08 18:03:28 +08009511 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009512 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9513
9514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9515 if (NULL == output_string)
9516 return RETURN_ERR;
9517
developerac6f1142022-12-20 19:26:35 +08009518 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009519 return RETURN_ERR;
9520 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 +08009521 _syscmd(cmd, buf, sizeof(buf));
9522
9523 //size of SSID name restricted to value less than 32 bytes
9524 snprintf(output_string, 32, "%s", buf);
9525 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9526
9527 return RETURN_OK;
9528}
9529
9530INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9531{
9532 //char cmd[MAX_CMD_SIZE] = {0};
9533 char config_file[MAX_BUF_SIZE] = {0};
9534 char buf[32] = {0};
9535
9536 if (!output_filterMode)
9537 return RETURN_ERR;
9538
9539 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9540 //_syscmd(cmd, buf, sizeof(buf));
9541 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08009542 if (!syn_flag)
9543 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
9544 else
developer07ded1f2024-01-10 10:30:15 +08009545 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer10adcc12022-09-13 14:39:17 +08009546 if(strlen(buf) == 0) {
9547 *output_filterMode = 0;
9548 }
9549 else {
9550 int macaddr_acl_mode = strtol(buf, NULL, 10);
9551 if (macaddr_acl_mode == 1) {
9552 *output_filterMode = 1;
9553 } else if (macaddr_acl_mode == 0) {
9554 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9555 if (strlen(buf) == 0) {
9556 *output_filterMode = 0;
9557 } else {
9558 *output_filterMode = 2;
9559 }
9560 } else {
9561 return RETURN_ERR;
9562 }
9563 }
developer06a01d92022-09-07 16:32:39 +08009564
9565 return RETURN_OK;
9566}
9567
9568INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9569{
9570 FILE *fp = NULL;
9571 char str[MAX_BUF_SIZE] = {0};
9572 int wificlientindex = 0 ;
9573 int count = 0;
9574 int signalstrength = 0;
9575 int arr[MACADDRESS_SIZE] = {0};
9576 unsigned char mac[MACADDRESS_SIZE] = {0};
9577 UINT wifi_count = 0;
9578 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9579 char pipeCmd[MAX_CMD_SIZE] = {0};
9580
9581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9582 *output_array_size = 0;
9583 *associated_dev_array = NULL;
9584 char interface_name[50] = {0};
9585
9586 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9587 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9588 return RETURN_ERR;
9589 }
9590
9591 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9592 fp = popen(pipeCmd, "r");
9593 if (fp == NULL)
9594 {
9595 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9596 return RETURN_ERR;
9597 }
9598
9599 /* Read the output a line at a time - output it. */
9600 fgets(str, sizeof(str)-1, fp);
9601 wifi_count = (unsigned int) atoi ( str );
9602 *output_array_size = wifi_count;
9603 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9604 pclose(fp);
9605
9606 if(wifi_count == 0)
9607 {
9608 return RETURN_OK;
9609 }
9610 else
9611 {
9612 wifi_associated_dev2_t* temp = NULL;
9613 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9614 *associated_dev_array = temp;
9615 if(temp == NULL)
9616 {
9617 printf("Error Statement. Insufficient memory \n");
9618 return RETURN_ERR;
9619 }
9620
9621 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9622 system(pipeCmd);
9623
9624 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9625 if(fp == NULL)
9626 {
9627 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9628 return RETURN_ERR;
9629 }
9630 fclose(fp);
9631
developer30423732022-12-01 16:17:49 +08009632 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009633 fp = popen(pipeCmd, "r");
9634 if(fp)
9635 {
9636 for(count =0 ; count < wifi_count; count++)
9637 {
9638 fgets(str, MAX_BUF_SIZE, fp);
9639 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9640 {
9641 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9642 {
9643 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9644
9645 }
9646 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9647 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]);
9648 }
9649 temp[count].cli_AuthenticationState = 1; //TODO
9650 temp[count].cli_Active = 1; //TODO
9651 }
9652 pclose(fp);
9653 }
9654
9655 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009656 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 +08009657 fp = popen(pipeCmd, "r");
9658 if(fp)
9659 {
9660 pclose(fp);
9661 }
9662 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9663 if(fp)
9664 {
9665 for(count =0 ; count < wifi_count ;count++)
9666 {
9667 fgets(str, MAX_BUF_SIZE, fp);
9668 signalstrength = atoi(str);
9669 temp[count].cli_RSSI = signalstrength;
9670 }
9671 pclose(fp);
9672 }
9673
9674
9675 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009676 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 +08009677 fp = popen(pipeCmd, "r");
9678 if (fp)
9679 {
9680 pclose(fp);
9681 }
9682 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9683 if (fp)
9684 {
9685 for (count = 0; count < wifi_count; count++)
9686 {
9687 fgets(str, MAX_BUF_SIZE, fp);
9688 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9689 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9690 }
9691 pclose(fp);
9692 }
9693
9694 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009695 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 +08009696 fp = popen(pipeCmd, "r");
9697 if (fp)
9698 {
9699 pclose(fp);
9700 }
9701 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9702 if (fp)
9703 {
9704 for (count = 0; count < wifi_count; count++)
9705 {
9706 fgets(str, MAX_BUF_SIZE, fp);
9707 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9708 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9709 }
9710 pclose(fp);
9711 }
9712 }
9713 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9714 return RETURN_OK;
9715
9716}
9717
9718INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9719{
9720#if 0
9721 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009722 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009723 _syscmd(cmd, buf, sizeof(buf));*/
9724
9725 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9726 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9727 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9728 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9729
9730 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.
9731 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].
9732 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].
9733 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].
9734 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9735 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9736
9737 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9738 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9739 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9740 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.
9741 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.
9742 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.
9743 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.
9744 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.
9745 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.
9746 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.
9747 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9748#endif
9749
9750 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009751 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009752 char pipeCmd[128] = {0};
9753 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009754 wifi_ssidTrafficStats2_t *out = output_struct;
9755
developerce736392022-09-13 15:24:34 +08009756 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009757 if (!output_struct)
9758 return RETURN_ERR;
9759
developerce736392022-09-13 15:24:34 +08009760 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009761 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009762 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009763 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009764
developer06a01d92022-09-07 16:32:39 +08009765 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009766 if (fp == NULL) {
9767 fprintf(stderr, "%s: popen failed\n", __func__);
9768 return RETURN_ERR;
9769 }
9770 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009771 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009772
developerce736392022-09-13 15:24:34 +08009773 if (strlen(str) == 0) // interface not exist
9774 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009775
developerce736392022-09-13 15:24:34 +08009776 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9777 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009778
developerce736392022-09-13 15:24:34 +08009779 memset(str, 0, sizeof(str));
9780 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009781 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009782 if (fp == NULL) {
9783 fprintf(stderr, "%s: popen failed\n", __func__);
9784 return RETURN_ERR;
9785 }
9786 fgets(str, sizeof(str), fp);
9787
9788 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9789 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009790 pclose(fp);
developerce736392022-09-13 15:24:34 +08009791
9792 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9793 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9794
9795 // Not supported
9796 output_struct->ssid_RetransCount = 0;
9797 output_struct->ssid_FailedRetransCount = 0;
9798 output_struct->ssid_RetryCount = 0;
9799 output_struct->ssid_MultipleRetryCount = 0;
9800 output_struct->ssid_ACKFailureCount = 0;
9801 output_struct->ssid_AggregatedPacketCount = 0;
9802
developer06a01d92022-09-07 16:32:39 +08009803 return RETURN_OK;
9804}
9805
9806//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).
9807INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9808{
9809 char output_val[16]={'\0'};
9810 char config_file[MAX_BUF_SIZE] = {0};
9811
9812 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9813 if (!output)
9814 return RETURN_ERR;
9815 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08009816 if (!syn_flag)
9817 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9818 else
developer07ded1f2024-01-10 10:30:15 +08009819 snprintf(output_val, sizeof(output_val), "%s", vap_info[apIndex].ap_isolate);
developer06a01d92022-09-07 16:32:39 +08009820 if( strcmp(output_val,"1") == 0 )
9821 *output = TRUE;
9822 else
9823 *output = FALSE;
9824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9825
9826 return RETURN_OK;
9827}
9828
9829INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9830{
9831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9832 char str[MAX_BUF_SIZE]={'\0'};
9833 char string[MAX_BUF_SIZE]={'\0'};
9834 char cmd[MAX_CMD_SIZE]={'\0'};
9835 char *ch;
9836 char config_file[MAX_BUF_SIZE] = {0};
9837 struct params params;
9838
9839 if(enable == TRUE)
9840 strcpy(string,"1");
9841 else
9842 strcpy(string,"0");
9843
9844 params.name = "ap_isolate";
9845 params.value = string;
9846
9847 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9848 wifi_hostapdWrite(config_file,&params,1);
developerefb790a2023-12-26 18:58:32 +08009849 snprintf(vap_info[apIndex].ap_isolate, sizeof(vap_info[apIndex].ap_isolate), "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08009850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9851
9852 return RETURN_OK;
9853}
9854
9855INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9856{
9857 if (NULL == output_dBm)
9858 return RETURN_ERR;
9859
9860 *output_dBm = 0;
9861 return RETURN_OK;
9862}
9863
9864INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9865{
9866 return RETURN_OK;
9867}
9868INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9869{
9870 return RETURN_OK;
9871}
9872INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9873{
9874 return RETURN_OK;
9875}
9876INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9877{
9878 return RETURN_OK;
9879}
9880INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9881{
9882 return RETURN_OK;
9883}
9884INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9885{
9886 char config_file[MAX_BUF_SIZE] = {0};
9887 struct params list;
9888
9889 list.name = "bss_transition";
9890 list.value = activate?"1":"0";
9891 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9892 wifi_hostapdWrite(config_file, &list, 1);
developerefb790a2023-12-26 18:58:32 +08009893 snprintf(vap_info[apIndex].bss_transition, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08009894
9895 return RETURN_OK;
9896}
9897wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9898
9899void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9900{
9901 return;
9902}
9903
9904INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9905{
9906 // TODO Implement me!
9907 return RETURN_OK;
9908}
9909
9910INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9911{
developera3c68b92022-09-13 15:27:29 +08009912 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009913 FILE *f = NULL;
9914
developer72ec5572023-01-05 16:27:13 +08009915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009916
developer72ec5572023-01-05 16:27:13 +08009917 if (essid == NULL)
9918 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009919
developer72ec5572023-01-05 16:27:13 +08009920 if (strlen(essid) == 0 || apIndex == -1) {
9921 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9922 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009923 }
9924
developer72ec5572023-01-05 16:27:13 +08009925 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9926 f = fopen(file_name, "w");
9927 if (f == NULL)
9928 return RETURN_ERR;
9929
9930 // For mode == 0 is to disable filter, just don't write ssid to the file.
9931 fprintf(f, "%d\n%s", mode, mode?essid:"");
9932 fclose(f);
9933 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009934 return RETURN_OK;
9935}
9936
9937INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9938{
9939 // TODO Implement me!
9940 //Apply wifi_pushRadioChannel() instantly
9941 return RETURN_ERR;
9942}
9943
9944INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9945{
9946 // TODO Implement me!
9947 return RETURN_OK;
9948}
9949
9950#ifdef HAL_NETLINK_IMPL
9951static int tidStats_callback(struct nl_msg *msg, void *arg) {
9952 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9953 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9954 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9955 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9956 int rem , tid_index = 0;
9957
9958 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9959 wifi_associated_dev_tid_entry_t *stats_entry;
9960
9961 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9962 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9963 };
9964 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9965 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9966 };
9967
9968 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9969 genlmsg_attrlen(gnlh, 0), NULL);
9970
9971
9972 if (!tb[NL80211_ATTR_STA_INFO]) {
9973 fprintf(stderr, "station stats missing!\n");
9974 return NL_SKIP;
9975 }
9976
9977 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9978 tb[NL80211_ATTR_STA_INFO],
9979 stats_policy)) {
9980 fprintf(stderr, "failed to parse nested attributes!\n");
9981 return NL_SKIP;
9982 }
9983
9984 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9985 {
9986 stats_entry = &out->tid_array[tid_index];
9987
9988 stats_entry->tid = tid_index;
9989 stats_entry->ac = _tid_ac_index_get[tid_index];
9990
9991 if(sinfo[NL80211_STA_INFO_TID_STATS])
9992 {
9993 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9994 printf("failed to parse nested stats attributes!");
9995 return NL_SKIP;
9996 }
9997 }
9998 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9999 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10000
10001 if(tid_index < (PS_MAX_TID - 1))
10002 tid_index++;
10003 }
10004 //ToDo: sum_time_ms, ewma_time_ms
10005 return NL_SKIP;
10006}
10007#endif
10008
10009INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
10010{
10011#ifdef HAL_NETLINK_IMPL
10012 Netlink nl;
10013 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010014 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010015
developerac6f1142022-12-20 19:26:35 +080010016 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010017 return RETURN_ERR;
10018
10019 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010020
10021 nl.id = initSock80211(&nl);
10022
10023 if (nl.id < 0) {
10024 fprintf(stderr, "Error initializing netlink \n");
10025 return -1;
10026 }
10027
10028 struct nl_msg* msg = nlmsg_alloc();
10029
10030 if (!msg) {
10031 fprintf(stderr, "Failed to allocate netlink message.\n");
10032 nlfree(&nl);
10033 return -2;
10034 }
10035
10036 genlmsg_put(msg,
10037 NL_AUTO_PORT,
10038 NL_AUTO_SEQ,
10039 nl.id,
10040 0,
10041 0,
10042 NL80211_CMD_GET_STATION,
10043 0);
10044
10045 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10046 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10047 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
10048 nl_send_auto(nl.socket, msg);
10049 nl_recvmsgs(nl.socket, nl.cb);
10050 nlmsg_free(msg);
10051 nlfree(&nl);
10052 return RETURN_OK;
10053#else
10054//iw implementation
10055#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10056#define TOTAL_MAX_LINES 50
10057
10058 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +080010059 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +080010060 FILE *fp=NULL;
10061 char pipeCmd[1024]= {'\0'};
10062 int lines,tid_index=0;
10063 char mac_addr[20] = {'\0'};
10064
developerac6f1142022-12-20 19:26:35 +080010065 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010066 return RETURN_ERR;
10067
developer06a01d92022-09-07 16:32:39 +080010068 wifi_associated_dev_tid_entry_t *stats_entry;
10069
developer06a01d92022-09-07 16:32:39 +080010070 strcpy(mac_addr,clientMacAddress);
10071
10072 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10073 fp= popen(pipeCmd,"r");
10074 if(fp == NULL)
10075 {
10076 perror("popen for station dump failed\n");
10077 return RETURN_ERR;
10078 }
10079 pclose(fp);
10080
10081 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10082 fp=popen(pipeCmd,"r");
10083 if(fp == NULL)
10084 {
10085 perror("popen for grep station failed\n");
10086 return RETURN_ERR;
10087 }
10088 else if(fgets(buf,sizeof(buf),fp) != NULL)
10089 lines=atoi(buf);
10090 else
10091 {
10092 pclose(fp);
10093 fprintf(stderr,"No devices are connected \n");
10094 return RETURN_ERR;
10095 }
10096 pclose(fp);
10097
10098 if(lines == 1)
10099 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10100
10101 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10102 {
10103 stats_entry = &tid_stats->tid_array[tid_index];
10104 stats_entry->tid = tid_index;
10105
10106 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);
10107
10108 fp=popen(pipeCmd,"r");
10109 if(fp ==NULL)
10110 {
10111 perror("Failed to read from tid file \n");
10112 return RETURN_ERR;
10113 }
10114 else if(fgets(buf,sizeof(buf),fp) != NULL)
10115 stats_entry->num_msdus = atol(buf);
10116
10117 pclose(fp);
10118 stats_entry->ac = _tid_ac_index_get[tid_index];
10119// TODO:
10120// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10121// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10122 }
10123 return RETURN_OK;
10124#endif
10125}
10126
10127
10128INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10129{
developerd946fd62022-12-08 18:03:28 +080010130 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +080010131 char cmd[128]={0};
10132 char buf[128]={0};
10133 int freq = 0;
10134
10135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10136
10137 // full mode is used to scan all channels.
10138 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10139 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10140 ieee80211_channel_to_frequency(chan_list[0], &freq);
10141
developerac6f1142022-12-20 19:26:35 +080010142 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010143 return RETURN_ERR;
10144
developer615510b2022-09-27 10:14:35 +080010145 if (freq)
developerd946fd62022-12-08 18:03:28 +080010146 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +080010147 else
developerd946fd62022-12-08 18:03:28 +080010148 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +080010149
10150 _syscmd(cmd, buf, sizeof(buf));
10151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10152
developer06a01d92022-09-07 16:32:39 +080010153 return RETURN_OK;
10154}
10155
10156
10157INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10158{
10159 // TODO Implement me!
10160 return RETURN_ERR;
10161}
10162
10163INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10164{
10165 // TODO Implement me!
10166 return RETURN_ERR;
10167}
10168
10169INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10170{
10171 // TODO Implement me!
10172 return RETURN_ERR;
10173}
10174
10175INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10176{
10177 // TODO Implement me!
10178 return RETURN_ERR;
10179}
10180
10181INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10182{
10183 // TODO Implement me!
10184 return RETURN_ERR;
10185}
10186
10187INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10188{
10189 // TODO Implement me!
10190 return RETURN_ERR;
10191}
10192
10193INT wifi_steering_eventUnregister(void)
10194{
10195 // TODO Implement me!
10196 return RETURN_ERR;
10197}
10198
10199INT wifi_delApAclDevices(INT apIndex)
10200{
10201#if 0
10202 char cmd[MAX_BUF_SIZE] = {0};
10203 char buf[MAX_BUF_SIZE] = {0};
10204
10205 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010206 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010207 if(_syscmd(cmd,buf,sizeof(buf)))
10208 return RETURN_ERR;
10209#endif
developer9988c232023-03-06 14:57:08 +080010210 char cmd[256]={0};
10211 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010212
developere6aafda2022-09-13 14:59:28 +080010213 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010214 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 +080010215 if(_syscmd(cmd, buf, sizeof(buf)))
10216 return RETURN_ERR;
10217 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010218
10219 return RETURN_OK;
10220}
10221
10222#ifdef HAL_NETLINK_IMPL
10223static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10224 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10225 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10226 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10227 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10228 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10229 char mac_addr[20],dev[20];
10230
10231 nla_parse(tb,
10232 NL80211_ATTR_MAX,
10233 genlmsg_attrdata(gnlh, 0),
10234 genlmsg_attrlen(gnlh, 0),
10235 NULL);
10236
10237 if(!tb[NL80211_ATTR_STA_INFO]) {
10238 fprintf(stderr, "sta stats missing!\n");
10239 return NL_SKIP;
10240 }
10241
10242 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10243 fprintf(stderr, "failed to parse nested attributes!\n");
10244 return NL_SKIP;
10245 }
10246 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10247
10248 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10249
10250 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10251 fprintf(stderr, "failed to parse nested rate attributes!");
10252 return NL_SKIP;
10253 }
10254
10255 if(sinfo[NL80211_STA_INFO_TID_STATS])
10256 {
10257 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10258 printf("failed to parse nested stats attributes!");
10259 return NL_SKIP;
10260 }
10261 }
10262
10263 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10264 {
10265 printf("Type is VHT\n");
10266 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10267 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10268
10269 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10270 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10271 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10272 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10273 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10274 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10275 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10276 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10277 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10278 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10279 }
10280 else
10281 {
10282 printf(" OFDM or CCK \n");
10283 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10284 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10285 }
10286
10287 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10288 if(rinfo[NL80211_RATE_INFO_MCS])
10289 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10290 }
10291 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10292 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10293 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10294 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10295
10296 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10297 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10298
10299 if (sinfo[NL80211_STA_INFO_SIGNAL])
10300 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10301 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10302 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10303 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10304 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10305 //rssi_array need to be filled
10306 return NL_SKIP;
10307}
10308#endif
10309
10310INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10311{
10312#ifdef HAL_NETLINK_IMPL
10313 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010314 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010315 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010316 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010317
10318 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10319
10320 if (*output_array_size <= 0)
10321 return RETURN_OK;
10322
developer06a01d92022-09-07 16:32:39 +080010323 nl.id = initSock80211(&nl);
10324
10325 if (nl.id < 0) {
10326 fprintf(stderr, "Error initializing netlink \n");
10327 return 0;
10328 }
10329
10330 struct nl_msg* msg = nlmsg_alloc();
10331
10332 if (!msg) {
10333 fprintf(stderr, "Failed to allocate netlink message.\n");
10334 nlfree(&nl);
10335 return 0;
10336 }
10337
10338 genlmsg_put(msg,
10339 NL_AUTO_PORT,
10340 NL_AUTO_SEQ,
10341 nl.id,
10342 0,
10343 0,
10344 NL80211_CMD_GET_STATION,
10345 0);
10346
10347 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10348 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10349 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10350 nl_send_auto(nl.socket, msg);
10351 nl_recvmsgs(nl.socket, nl.cb);
10352 nlmsg_free(msg);
10353 nlfree(&nl);
10354 return RETURN_OK;
10355#else
10356 //TODO Implement me
10357 return RETURN_OK;
10358#endif
10359}
10360
10361#ifdef HAL_NETLINK_IMPL
10362static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10363 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10364 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10365 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10366 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10367 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10368 char mac_addr[20],dev[20];
10369
10370 nla_parse(tb,
10371 NL80211_ATTR_MAX,
10372 genlmsg_attrdata(gnlh, 0),
10373 genlmsg_attrlen(gnlh, 0),
10374 NULL);
10375
10376 if(!tb[NL80211_ATTR_STA_INFO]) {
10377 fprintf(stderr, "sta stats missing!\n");
10378 return NL_SKIP;
10379 }
10380
10381 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10382 fprintf(stderr, "failed to parse nested attributes!\n");
10383 return NL_SKIP;
10384 }
10385
10386 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10387
10388 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10389
10390 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10391 fprintf(stderr, "failed to parse nested rate attributes!");
10392 return NL_SKIP;
10393 }
10394
10395 if(sinfo[NL80211_STA_INFO_TID_STATS])
10396 {
10397 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10398 printf("failed to parse nested stats attributes!");
10399 return NL_SKIP;
10400 }
10401 }
10402 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10403 {
10404 printf("Type is VHT\n");
10405 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10406 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10407
10408 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10409 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10410 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10411 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10412 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10413 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10414 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10415 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10416 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10417 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10418 }
10419 else
10420 {
10421 printf(" OFDM or CCK \n");
10422 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10423 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10424 }
10425
10426 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10427 if(rinfo[NL80211_RATE_INFO_MCS])
10428 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10429 }
10430
10431 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10432 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10433 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10434 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10435
10436 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10437 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10438 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10439
10440 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10441 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10442
10443 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10444 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10445
10446 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10447 ((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]);
10448
10449 return NL_SKIP;
10450}
10451#endif
10452
10453INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10454{
10455#ifdef HAL_NETLINK_IMPL
10456 Netlink nl;
10457 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010458 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010459 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010460 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010461
10462 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10463
10464 if (*output_array_size <= 0)
10465 return RETURN_OK;
10466
developerd946fd62022-12-08 18:03:28 +080010467 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010468
10469 nl.id = initSock80211(&nl);
10470
10471 if(nl.id < 0) {
10472 fprintf(stderr, "Error initializing netlink \n");
10473 return 0;
10474 }
10475
10476 struct nl_msg* msg = nlmsg_alloc();
10477
10478 if(!msg) {
10479 fprintf(stderr, "Failed to allocate netlink message.\n");
10480 nlfree(&nl);
10481 return 0;
10482 }
10483
10484 genlmsg_put(msg,
10485 NL_AUTO_PORT,
10486 NL_AUTO_SEQ,
10487 nl.id,
10488 0,
10489 0,
10490 NL80211_CMD_GET_STATION,
10491 0);
10492
10493 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10494 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10495 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10496 nl_send_auto(nl.socket, msg);
10497 nl_recvmsgs(nl.socket, nl.cb);
10498 nlmsg_free(msg);
10499 nlfree(&nl);
10500 return RETURN_OK;
10501#else
10502 //TODO Implement me
10503 return RETURN_OK;
10504#endif
10505}
10506
10507INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10508{
10509 // TODO Implement me!
10510 char buf[MAX_BUF_SIZE] = {0};
10511 char config_file[MAX_BUF_SIZE] = {0};
10512
10513 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +080010514 if (!syn_flag)
10515 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10516 else
developer07ded1f2024-01-10 10:30:15 +080010517 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].bss_transition);
developer06a01d92022-09-07 16:32:39 +080010518 *activate = (strncmp("1",buf,1) == 0);
10519
10520 return RETURN_OK;
10521}
10522
10523INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10524{
10525 char config_file[MAX_BUF_SIZE] = {0};
10526 struct params list;
10527
10528 list.name = "rrm_neighbor_report";
10529 list.value = activate?"1":"0";
10530 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10531 wifi_hostapdWrite(config_file, &list, 1);
10532
10533 return RETURN_OK;
10534}
10535
10536INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10537{
10538 char buf[32] = {0};
10539 char config_file[MAX_BUF_SIZE] = {0};
10540
10541 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10542 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10543 *activate = (strncmp("1",buf,1) == 0);
10544
10545 return RETURN_OK;
10546}
10547#undef HAL_NETLINK_IMPL
10548#ifdef HAL_NETLINK_IMPL
10549static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10550 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10551 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10552 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10553 char dev[20];
10554 int freq =0 ;
10555 static int i=0;
10556
10557 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10558
10559 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10560 };
10561
10562 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10563
10564 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10565
10566 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10567 fprintf(stderr, "survey data missing!\n");
10568 return NL_SKIP;
10569 }
10570
10571 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10572 {
10573 fprintf(stderr, "failed to parse nested attributes!\n");
10574 return NL_SKIP;
10575 }
10576
10577
10578 if(out[0].array_size == 1 )
10579 {
10580 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10581 {
10582 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10583 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10584 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10585
10586 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10587 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10588 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10589 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10590 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10591 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10592 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10593 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10594 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10595 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10596 if (sinfo[NL80211_SURVEY_INFO_TIME])
10597 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10598 return NL_STOP;
10599 }
10600 }
10601 else
10602 {
10603 if ( i <= out[0].array_size )
10604 {
10605 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10606 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10607 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10608
10609 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10610 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10611 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10612 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10613 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10614 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10615 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10616 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10617 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10618 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10619 if (sinfo[NL80211_SURVEY_INFO_TIME])
10620 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10621 }
10622 }
10623
10624 i++;
10625 return NL_SKIP;
10626}
10627#endif
10628
10629static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10630{
10631 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10632 FILE *fp;
10633
10634 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10635 {
10636 printf("Creating Frequency-Channel Map\n");
10637 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10638 }
10639 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10640 if((fp = popen(command, "r")))
10641 {
10642 fgets(output, sizeof(output), fp);
10643 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010644 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010645 }
10646
10647 return 0;
10648}
10649
10650static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10651{
10652 int freqMHz = -1;
10653 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010654 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010655
10656 ieee80211_channel_to_frequency(channel, &freqMHz);
10657 if (freqMHz == -1) {
10658 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10659 return -1;
10660 }
10661
developer7930d352022-12-21 17:55:42 +080010662 wifi_GetInterfaceName(radioIndex, interface_name);
10663 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010664 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10665 radioIndex, freqMHz);
10666 return -1;
10667 }
10668
10669 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10670 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10671 return -1;
10672 }
10673
10674 return 0;
10675}
10676
10677static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10678{
10679 const char *ptr = buf;
10680 char *key = NULL;
10681 char *val = NULL;
10682 char line[256] = { '\0' };
10683
10684 while (ptr = get_line_from_str_buf(ptr, line)) {
10685 if (strstr(line, "Frequency")) continue;
10686
10687 key = strtok(line, ":");
10688 val = strtok(NULL, " ");
10689 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10690
10691 if (!strcmp(key, "noise")) {
10692 sscanf(val, "%d", &stats->ch_noise);
10693 if (stats->ch_noise == 0) {
10694 // Workaround for missing noise information.
10695 // Assume -95 for 2.4G and -103 for 5G
10696 if (radioIndex == 0) stats->ch_noise = -95;
10697 if (radioIndex == 1) stats->ch_noise = -103;
10698 }
10699 }
10700 else if (!strcmp(key, "channel active time")) {
10701 sscanf(val, "%llu", &stats->ch_utilization_total);
10702 }
10703 else if (!strcmp(key, "channel busy time")) {
10704 sscanf(val, "%llu", &stats->ch_utilization_busy);
10705 }
10706 else if (!strcmp(key, "channel receive time")) {
10707 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10708 }
10709 else if (!strcmp(key, "channel transmit time")) {
10710 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10711 }
10712 };
10713
10714 return 0;
10715}
10716
10717INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10718{
10719 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10720#ifdef HAL_NETLINK_IMPL
10721 Netlink nl;
10722 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010723 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010724
10725 local[0].array_size = array_size;
10726
developerac6f1142022-12-20 19:26:35 +080010727 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010728 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010729
10730 nl.id = initSock80211(&nl);
10731
10732 if (nl.id < 0) {
10733 fprintf(stderr, "Error initializing netlink \n");
10734 return -1;
10735 }
10736
10737 struct nl_msg* msg = nlmsg_alloc();
10738
10739 if (!msg) {
10740 fprintf(stderr, "Failed to allocate netlink message.\n");
10741 nlfree(&nl);
10742 return -2;
10743 }
10744
10745 genlmsg_put(msg,
10746 NL_AUTO_PORT,
10747 NL_AUTO_SEQ,
10748 nl.id,
10749 0,
10750 NLM_F_DUMP,
10751 NL80211_CMD_GET_SURVEY,
10752 0);
10753
10754 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10755 nl_send_auto(nl.socket, msg);
10756 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10757 nl_recvmsgs(nl.socket, nl.cb);
10758 nlmsg_free(msg);
10759 nlfree(&nl);
10760 //Copying the Values
10761 for(int i=0;i<array_size;i++)
10762 {
10763 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10764 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10765 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10766 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10767 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10768 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10769 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10770 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10771 }
10772#else
10773 ULONG channel = 0;
10774 int i;
10775 int number_of_channels = array_size;
10776 char buf[512];
10777 INT ret;
10778 wifi_channelStats_t tmp_stats;
10779
10780 if (number_of_channels == 0) {
10781 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10782 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10783 return RETURN_ERR;
10784 }
10785 number_of_channels = 1;
10786 input_output_channelStats_array[0].ch_number = channel;
10787 }
10788
10789 for (i = 0; i < number_of_channels; i++) {
10790
10791 input_output_channelStats_array[i].ch_noise = 0;
10792 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10793 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10794 input_output_channelStats_array[i].ch_utilization_busy = 0;
10795 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10796 input_output_channelStats_array[i].ch_utilization_total = 0;
10797
10798 memset(buf, 0, sizeof(buf));
10799 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10800 return RETURN_ERR;
10801 }
10802 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10803 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10804 return RETURN_ERR;
10805 }
10806
10807 // XXX: fake missing 'self' counter which is not available in iw survey output
10808 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10809 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10810
10811 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10812 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10813 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10814 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10815 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10816
10817 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",
10818 __func__,
10819 input_output_channelStats_array[i].ch_number,
10820 input_output_channelStats_array[i].ch_noise,
10821 input_output_channelStats_array[i].ch_utilization_total,
10822 input_output_channelStats_array[i].ch_utilization_busy,
10823 input_output_channelStats_array[i].ch_utilization_busy_rx,
10824 input_output_channelStats_array[i].ch_utilization_busy_tx,
10825 input_output_channelStats_array[i].ch_utilization_busy_self,
10826 input_output_channelStats_array[i].ch_utilization_busy_ext);
10827 }
10828#endif
10829 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10830 return RETURN_OK;
10831}
10832#define HAL_NETLINK_IMPL
10833
10834/* Hostapd events */
10835
10836#ifndef container_of
10837#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10838#define container_of(ptr, type, member) \
10839 ((type *)((char *)ptr - offset_of(type, member)))
10840#endif /* container_of */
10841
10842struct ctrl {
10843 char sockpath[128];
10844 char sockdir[128];
10845 char bss[IFNAMSIZ];
10846 char reply[4096];
10847 int ssid_index;
10848 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10849 void (*overrun)(struct ctrl *ctrl);
10850 struct wpa_ctrl *wpa;
10851 unsigned int ovfl;
10852 size_t reply_len;
10853 int initialized;
10854 ev_timer retry;
10855 ev_timer watchdog;
10856 ev_stat stat;
10857 ev_io io;
10858};
10859static wifi_newApAssociatedDevice_callback clients_connect_cb;
10860static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10861static struct ctrl wpa_ctrl[MAX_APS];
10862static int initialized;
10863
10864static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10865{
10866 char cbuf[256] = {};
10867 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10868 struct cmsghdr *cmsg;
10869 unsigned int ovfl = ctrl->ovfl;
10870 unsigned int drop;
10871
10872 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10873 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10874 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10875 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10876
10877 drop = ovfl - ctrl->ovfl;
10878 ctrl->ovfl = ovfl;
10879
10880 return drop;
10881}
10882
10883static void ctrl_close(struct ctrl *ctrl)
10884{
10885 if (ctrl->io.cb)
10886 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10887 if (ctrl->retry.cb)
10888 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10889 if (!ctrl->wpa)
10890 return;
10891
10892 wpa_ctrl_detach(ctrl->wpa);
10893 wpa_ctrl_close(ctrl->wpa);
10894 ctrl->wpa = NULL;
10895 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10896}
10897
10898static void ctrl_process(struct ctrl *ctrl)
10899{
10900 const char *str;
10901 int drops;
10902 int level;
10903 int err;
10904
10905 /* Example events:
10906 *
10907 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10908 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10909 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10910 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10911 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10912 */
10913 if (!(str = index(ctrl->reply, '>')))
10914 return;
10915 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10916 return;
10917
10918 str++;
10919
10920 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10921 if (!(str = index(ctrl->reply, ' ')))
10922 return;
10923 wifi_associated_dev_t sta;
10924 memset(&sta, 0, sizeof(sta));
10925
10926 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10927 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10928 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10929
10930 sta.cli_Active=true;
10931
10932 (clients_connect_cb)(ctrl->ssid_index, &sta);
10933 goto handled;
10934 }
10935
10936 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10937 if (!(str = index(ctrl->reply, ' ')))
10938 return;
10939
10940 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10941 goto handled;
10942 }
10943
10944 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10945 printf("CTRL_WPA: handle TERMINATING event\n");
10946 goto retry;
10947 }
10948
10949 if (strncmp("AP-DISABLED", str, 11) == 0) {
10950 printf("CTRL_WPA: handle AP-DISABLED\n");
10951 goto retry;
10952 }
10953
10954 printf("Event not supported!!\n");
10955
10956handled:
10957
10958 if ((drops = ctrl_get_drops(ctrl))) {
10959 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10960 if (ctrl->overrun)
10961 ctrl->overrun(ctrl);
10962 }
10963
10964 return;
10965
10966retry:
10967 printf("WPA_CTRL: closing\n");
10968 ctrl_close(ctrl);
10969 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10970 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10971}
10972
10973static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10974{
10975 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10976 int err;
10977
10978 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10979 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10980 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10981 ctrl->reply[ctrl->reply_len] = 0;
10982 if (err < 0) {
10983 if (errno == EAGAIN || errno == EWOULDBLOCK)
10984 return;
10985 ctrl_close(ctrl);
10986 ev_timer_again(EV_A_ &ctrl->retry);
10987 return;
10988 }
10989
10990 ctrl_process(ctrl);
10991}
10992
10993static int ctrl_open(struct ctrl *ctrl)
10994{
10995 int fd;
10996
10997 if (ctrl->wpa)
10998 return 0;
10999
11000 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
11001 if (!ctrl->wpa)
11002 goto err;
11003
11004 if (wpa_ctrl_attach(ctrl->wpa) < 0)
11005 goto err_close;
11006
11007 fd = wpa_ctrl_get_fd(ctrl->wpa);
11008 if (fd < 0)
11009 goto err_detach;
11010
11011 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
11012 goto err_detach;
11013
11014 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11015 ev_io_start(EV_DEFAULT_ &ctrl->io);
11016
11017 return 0;
11018
11019err_detach:
11020 wpa_ctrl_detach(ctrl->wpa);
11021err_close:
11022 wpa_ctrl_close(ctrl->wpa);
11023err:
11024 ctrl->wpa = NULL;
11025 return -1;
11026}
11027
11028static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11029{
11030 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11031
11032 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11033 ctrl_open(ctrl);
11034}
11035
11036static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11037{
11038 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11039
11040 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11041 if (ctrl_open(ctrl) == 0) {
11042 printf("WPA_CTRL: retry successful\n");
11043 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11044 }
11045}
11046
11047int ctrl_enable(struct ctrl *ctrl)
11048{
11049 if (ctrl->wpa)
11050 return 0;
11051
11052 if (!ctrl->stat.cb) {
11053 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11054 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11055 }
11056
11057 if (!ctrl->retry.cb) {
11058 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11059 }
11060
11061 return ctrl_open(ctrl);
11062}
11063
11064static void
11065ctrl_msg_cb(char *buf, size_t len)
11066{
11067 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11068
11069 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11070 ctrl_process(ctrl);
11071}
11072
11073static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11074{
11075 int err;
11076
11077 if (!ctrl->wpa)
11078 return -1;
11079 if (*reply_len < 2)
11080 return -1;
11081
11082 (*reply_len)--;
11083 ctrl->reply_len = sizeof(ctrl->reply);
11084 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11085 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11086 if (err < 0)
11087 return err;
11088
11089 if (ctrl->reply_len > *reply_len)
11090 ctrl->reply_len = *reply_len;
11091
11092 *reply_len = ctrl->reply_len;
11093 memcpy(reply, ctrl->reply, *reply_len);
11094 reply[*reply_len - 1] = 0;
11095 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11096 return 0;
11097}
11098
11099static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11100{
11101 const char *pong = "PONG";
11102 const char *ping = "PING";
11103 char reply[1024];
11104 size_t len = sizeof(reply);
11105 int err;
11106 ULONG s, snum;
11107 INT ret;
11108 BOOL status;
11109
11110 printf("WPA_CTRL: watchdog cb\n");
11111
11112 ret = wifi_getSSIDNumberOfEntries(&snum);
11113 if (ret != RETURN_OK) {
11114 printf("%s: failed to get SSID count", __func__);
11115 return;
11116 }
11117
11118 if (snum > MAX_APS) {
11119 printf("more ssid than supported! %lu\n", snum);
11120 return;
11121 }
11122
11123 for (s = 0; s < snum; s++) {
11124 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080011125 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080011126 continue;
11127 }
11128 if (status == false) continue;
11129
11130 memset(reply, 0, sizeof(reply));
11131 len = sizeof(reply);
11132 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11133 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11134 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11135 continue;
11136
11137 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11138 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080011139 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080011140 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11141 }
11142}
11143
11144static int init_wpa()
11145{
11146 int ret = 0, i = 0;
11147 ULONG s, snum;
11148
11149 ret = wifi_getSSIDNumberOfEntries(&snum);
11150 if (ret != RETURN_OK) {
11151 printf("%s: failed to get SSID count", __func__);
11152 return RETURN_ERR;
11153 }
11154
11155 if (snum > MAX_APS) {
11156 printf("more ssid than supported! %lu\n", snum);
11157 return RETURN_ERR;
11158 }
11159
11160 for (s = 0; s < snum; s++) {
11161 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11162 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11163 wpa_ctrl[s].ssid_index = s;
11164 ctrl_enable(&wpa_ctrl[s]);
11165 }
11166
11167 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11168 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11169
11170 initialized = 1;
11171 printf("WPA_CTRL: initialized\n");
11172
11173 return RETURN_OK;
11174}
11175
11176void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11177{
11178 clients_connect_cb = callback_proc;
11179 if (!initialized)
11180 init_wpa();
11181}
11182
11183void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11184{
11185 clients_disconnect_cb = callback_proc;
11186 if (!initialized)
11187 init_wpa();
11188}
11189
11190INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11191{
11192 // TODO Implement me!
11193 return RETURN_ERR;
11194}
11195
11196INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11197{
11198 // TODO Implement me!
11199 return RETURN_ERR;
11200}
11201
11202INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11203{
11204 int i;
developer4b102122023-02-15 10:53:03 +080011205 int phyId = -1;
11206 char cmd[256] = {0};
11207 char channel_numbers_buf[256] = {0};
11208 char dfs_state_buf[256] = {0};
11209 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011210 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011211 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080011212
developer4b102122023-02-15 10:53:03 +080011213 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011214
developer4b102122023-02-15 10:53:03 +080011215 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11216 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011217
developer4b102122023-02-15 10:53:03 +080011218 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 +080011219
developer4b102122023-02-15 10:53:03 +080011220 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11221 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11222 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011223 }
11224
developer4b102122023-02-15 10:53:03 +080011225 ptr = channel_numbers_buf;
11226 i = 0;
11227 while (ptr = get_line_from_str_buf(ptr, line)) {
11228 if (i >= outputMapSize) {
11229 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11230 return RETURN_ERR;
11231 }
11232 sscanf(line, "%d", &outputMap[i].ch_number);
11233
11234 memset(cmd, 0, sizeof(cmd));
11235 // Below command should fetch string for DFS state (usable, available or unavailable)
11236 // Example line: "DFS state: usable (for 78930 sec)"
11237 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) {
11238 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011239 return RETURN_ERR;
11240 }
11241
developer4b102122023-02-15 10:53:03 +080011242 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11243 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011244 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11245 return RETURN_ERR;
11246 }
11247
developer4b102122023-02-15 10:53:03 +080011248 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011249
developer4b102122023-02-15 10:53:03 +080011250 if (!strcmp(dfs_state_buf, "usable")) {
11251 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11252 } else if (!strcmp(dfs_state_buf, "available")) {
11253 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11254 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11255 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11256 } else {
11257 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011258 }
developer4b102122023-02-15 10:53:03 +080011259 i++;
developer06a01d92022-09-07 16:32:39 +080011260 }
11261
developer4b102122023-02-15 10:53:03 +080011262 return RETURN_OK;
11263
developer06a01d92022-09-07 16:32:39 +080011264 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11265 return RETURN_ERR;
11266}
11267
11268INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11269{
11270 // TODO Implement me!
11271 return RETURN_ERR;
11272}
11273
11274INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11275{
11276 return RETURN_OK;
11277}
11278
11279INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11280{
11281 // TODO Implement me!
11282 return RETURN_ERR;
11283}
11284
11285INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11286{
11287 // TODO API refrence Implementaion is present on RPI hal
11288 return RETURN_ERR;
11289}
11290
developerfeab1d12023-09-27 11:29:38 +080011291
developer06a01d92022-09-07 16:32:39 +080011292INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11293{
developera5005b62022-09-13 15:43:35 +080011294 char cmd[128]={'\0'};
11295 char buf[128]={'\0'};
developerfeab1d12023-09-27 11:29:38 +080011296 int radioIndex = -1;
11297 int phyIndex = -1;
11298 bool enabled = false;
11299 int cur_tx_dbm = 0;
developera5005b62022-09-13 15:43:35 +080011300
11301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfeab1d12023-09-27 11:29:38 +080011302
developera5005b62022-09-13 15:43:35 +080011303 if(txpwr_pcntg == NULL)
11304 return RETURN_ERR;
11305
developerfeab1d12023-09-27 11:29:38 +080011306 // The API name as getRadioXXX, I think the input index should be radioIndex,
11307 // but current we not change the name, but use it as radioIndex
11308 radioIndex = apIndex;
11309 phyIndex = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +080011310
developera5005b62022-09-13 15:43:35 +080011311 // Get the maximum tx power of the device
developerfeab1d12023-09-27 11:29:38 +080011312 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11313 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011314 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011315 if (strcmp(buf, "enable") == 0)
11316 enabled = true;
developera5005b62022-09-13 15:43:35 +080011317
developerfeab1d12023-09-27 11:29:38 +080011318 if (!enabled) {
11319 *txpwr_pcntg = 100;
11320 return RETURN_OK;
11321 }
11322
developera5005b62022-09-13 15:43:35 +080011323 memset(cmd, 0, sizeof(cmd));
11324 memset(buf, 0, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011325 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11326 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011327 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011328 cur_tx_dbm = strtol(buf, NULL, 10);
developera5005b62022-09-13 15:43:35 +080011329
developerfeab1d12023-09-27 11:29:38 +080011330 switch (cur_tx_dbm) {
11331 case 0:
11332 *txpwr_pcntg = 100; // range 91-100
developera5005b62022-09-13 15:43:35 +080011333 break;
developerfeab1d12023-09-27 11:29:38 +080011334 case 1:
11335 *txpwr_pcntg = 75; // range 61-90
11336 break;
11337 case 3:
11338 *txpwr_pcntg = 50; // range 31-60
11339 break;
11340 case 6:
11341 *txpwr_pcntg = 25; // range 16-30
11342 break;
11343 case 9:
11344 *txpwr_pcntg = 12; // range 10-15
11345 break;
11346 case 12:
11347 *txpwr_pcntg = 6; // range 1-9
11348 break;
11349 default:
11350 *txpwr_pcntg = 100; // 0
developera5005b62022-09-13 15:43:35 +080011351 }
developerfeab1d12023-09-27 11:29:38 +080011352
developer06a01d92022-09-07 16:32:39 +080011353 return RETURN_OK;
11354}
11355
11356INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11357{
developer58599c22022-09-13 16:40:34 +080011358 // TODO precac feature.
11359 struct params params = {0};
11360 char config_file[128] = {0};
11361
11362 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11363
11364 params.name = "enable_background_radar";
11365 params.value = enable?"1":"0";
11366 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11367 wifi_hostapdWrite(config_file, &params, 1);
11368 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11369
11370 /* TODO precac feature */
11371
11372 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11373 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011374}
11375
11376INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11377{
developer58599c22022-09-13 16:40:34 +080011378 char config_file[128] = {0};
11379 char buf[64] = {0};
11380
11381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11382 if (NULL == enable || NULL == precac)
11383 return RETURN_ERR;
11384
11385 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11386 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011387 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011388 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011389 *precac = true;
11390 } else {
developer58599c22022-09-13 16:40:34 +080011391 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011392 *precac = false;
11393 }
developer58599c22022-09-13 16:40:34 +080011394
11395 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11396 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011397}
11398
11399INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11400{
developer58599c22022-09-13 16:40:34 +080011401 *supported = TRUE;
11402 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011403}
11404
developera7149722023-01-11 11:36:21 +080011405bool check_is_hemu_vendor_new_patch() {
11406 char cmd[128] = {0};
11407 char buf[128] = {0};
11408
11409 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11410 _syscmd(cmd, buf, sizeof(buf));
11411
11412 if (strlen(buf) > 0)
11413 return FALSE;
11414 else
11415 return TRUE;
11416}
11417
developer3e6b1692022-09-30 18:04:05 +080011418INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11419{
11420 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11421 struct params params = {0};
11422 char config_file[64] = {0};
11423 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011424 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011425 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011426 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011427 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11428
developera7149722023-01-11 11:36:21 +080011429 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011430
11431 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11432 set_mu_type &= ~0x05; // unset bit 0, 2
11433 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11434 set_mu_type |= 0x01;
11435 set_mu_type &= ~0x04;
11436 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11437 set_mu_type &= ~0x01;
11438 set_mu_type |= 0x04;
11439 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11440 set_mu_type |= 0x05; // set bit 0, 2
11441 }
11442
developera7149722023-01-11 11:36:21 +080011443 new_vendor_patch = check_is_hemu_vendor_new_patch();
11444 if (new_vendor_patch)
11445 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11446 else
11447 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11448
11449 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011450 sprintf(buf, "%u", set_mu_type);
11451 params.value = buf;
11452 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11453 wifi_hostapdWrite(config_file, &params, 1);
11454 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011455 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011456
11457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11458 return RETURN_OK;
11459}
11460
11461INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11462{
11463 struct params params={0};
11464 char config_file[64] = {0};
11465 char buf[64] = {0};
11466 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011467 bool new_vendor_patch = FALSE;
11468 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011469
11470 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11471
11472 if (mu_type == NULL)
11473 return RETURN_ERR;
11474
developera7149722023-01-11 11:36:21 +080011475 new_vendor_patch = check_is_hemu_vendor_new_patch();
11476
11477 if (new_vendor_patch)
11478 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11479 else
11480 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11481
developer3e6b1692022-09-30 18:04:05 +080011482 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011483 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011484 get_mu_type = strtol(buf, NULL, 10);
11485
11486 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11487 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11488 else if (get_mu_type & 0x04)
11489 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11490 else if (get_mu_type & 0x01)
11491 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11492 else
11493 *mu_type = WIFI_DL_MU_TYPE_NONE;
11494
11495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11496 return RETURN_OK;
11497}
11498
11499INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11500{
11501 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11502 struct params params={0};
11503 char config_file[64] = {0};
11504 char buf[64] = {0};
11505 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011506 bool new_vendor_patch = FALSE;
11507 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011508 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11509
developera7149722023-01-11 11:36:21 +080011510 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011511
11512 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11513 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11514 set_mu_type &= ~0x0a;
11515 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11516 set_mu_type |= 0x02;
11517 set_mu_type &= ~0x08;
11518 }
11519
developera7149722023-01-11 11:36:21 +080011520 new_vendor_patch = check_is_hemu_vendor_new_patch();
11521
11522 if (new_vendor_patch)
11523 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11524 else
11525 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11526
11527 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011528 sprintf(buf, "%u", set_mu_type);
11529 params.value = buf;
11530 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11531 wifi_hostapdWrite(config_file, &params, 1);
11532 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011533 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011534
11535 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11536 return RETURN_OK;
11537}
11538
11539INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11540{
11541 struct params params={0};
11542 char config_file[64] = {0};
11543 char buf[64] = {0};
11544 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011545 bool new_vendor_patch = FALSE;
11546 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011547
11548 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11549
developera7149722023-01-11 11:36:21 +080011550 new_vendor_patch = check_is_hemu_vendor_new_patch();
11551
11552 if (new_vendor_patch)
11553 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11554 else
11555 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11556
developer3e6b1692022-09-30 18:04:05 +080011557 if (mu_type == NULL)
11558 return RETURN_ERR;
11559
11560 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011561 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011562
11563 get_mu_type = strtol(buf, NULL, 10);
11564 if (get_mu_type & 0x02)
11565 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11566 else
11567 *mu_type = WIFI_DL_MU_TYPE_NONE;
11568
11569 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11570 return RETURN_OK;
11571}
11572
11573
developer454b9462022-09-13 15:29:16 +080011574INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11575{
11576 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011577 char buf[256] = {0};
11578 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011579 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011580 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011581 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011582 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011583
11584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11585
developer254882b2022-09-30 17:12:31 +080011586 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011587 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11588 return RETURN_ERR;
11589 }
developer454b9462022-09-13 15:29:16 +080011590
developer254882b2022-09-30 17:12:31 +080011591 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011592 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011593
developer254882b2022-09-30 17:12:31 +080011594 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11595 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011596 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011597 _syscmd(cmd, buf, sizeof(buf));
11598 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11599 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11600 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011601 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 +080011602 _syscmd(cmd, buf, sizeof(buf));
11603 }
11604 if (band == band_5) {
11605 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11606 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011607 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 +080011608 _syscmd(cmd, buf, sizeof(buf));
11609 }
11610 }
11611 }
11612 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011613
developer254882b2022-09-30 17:12:31 +080011614 if (guard_interval == wifi_guard_interval_400)
11615 strcpy(GI, "0.4");
11616 else if (guard_interval == wifi_guard_interval_800)
11617 strcpy(GI, "0.8");
11618 else if (guard_interval == wifi_guard_interval_1600)
11619 strcpy(GI, "1.6");
11620 else if (guard_interval == wifi_guard_interval_3200)
11621 strcpy(GI, "3.2");
11622 else if (guard_interval == wifi_guard_interval_auto)
11623 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011624 // Record GI for get GI function
11625 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11626 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011627 if (f == NULL)
11628 return RETURN_ERR;
11629 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011630 fclose(f);
11631 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11632 return RETURN_OK;
11633}
11634
11635INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11636{
11637 char buf[32] = {0};
11638 char cmd[64] = {0};
11639
11640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11641
11642 if (guard_interval == NULL)
11643 return RETURN_ERR;
11644
developer7c4cd202023-03-01 10:56:29 +080011645 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011646 _syscmd(cmd, buf, sizeof(buf));
11647
11648 if (strncmp(buf, "0.4", 3) == 0)
11649 *guard_interval = wifi_guard_interval_400;
11650 else if (strncmp(buf, "0.8", 3) == 0)
11651 *guard_interval = wifi_guard_interval_800;
11652 else if (strncmp(buf, "1.6", 3) == 0)
11653 *guard_interval = wifi_guard_interval_1600;
11654 else if (strncmp(buf, "3.2", 3) == 0)
11655 *guard_interval = wifi_guard_interval_3200;
11656 else
11657 *guard_interval = wifi_guard_interval_auto;
11658
11659 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11660 return RETURN_OK;
11661}
11662
developer3cc61d12022-09-13 16:36:05 +080011663INT wifi_setBSSColor(INT radio_index, UCHAR color)
11664{
11665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11666 struct params params = {0};
11667 char config_file[128] = {0};
11668 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011669 UCHAR *color_list;
11670 int color_num = 0;
11671 int maxNumberColors = 64;
11672 BOOL color_is_aval = FALSE;
11673
developerbf0b9dc2023-07-06 14:30:54 +080011674 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011675 return RETURN_ERR;
11676
developer517f3be2023-05-08 10:02:39 +080011677 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11678 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11679 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011680 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011681 }
developer2acb9632023-03-14 14:58:31 +080011682
11683 for (int i = 0; i < color_num; i++) {
11684 if (color_list[i] == color) {
11685 color_is_aval = TRUE;
11686 break;
11687 }
11688 }
11689 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011690 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011691 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11692 return RETURN_ERR;
11693 }
developer3cc61d12022-09-13 16:36:05 +080011694
11695 params.name = "he_bss_color";
11696 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11697 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011698 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011699 wifi_hostapdWrite(config_file, &params, 1);
11700 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011701 wifi_reloadAp(radio_index);
11702
developer517f3be2023-05-08 10:02:39 +080011703 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11705 return RETURN_OK;
11706}
11707
11708INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11709{
developer3cc61d12022-09-13 16:36:05 +080011710 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011711 char cmd[128] = {0};
11712 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011713
developer3cc61d12022-09-13 16:36:05 +080011714 if (NULL == color)
11715 return RETURN_ERR;
11716
developer2acb9632023-03-14 14:58:31 +080011717 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11718 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011719
developer2acb9632023-03-14 14:58:31 +080011720 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11721 _syscmd(cmd, buf, sizeof(buf));
11722 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011723
developer2acb9632023-03-14 14:58:31 +080011724 return RETURN_OK;
11725}
11726
11727INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11728{
11729 char buf[64] = {0};
11730 char cmd[128] = {0};
11731 char interface_name[16] = {0};
11732 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011733
developer2acb9632023-03-14 14:58:31 +080011734 if (NULL == colorList || NULL == numColorReturned)
11735 return RETURN_ERR;
11736
11737 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11738 return RETURN_ERR;
11739
11740 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11741 _syscmd(cmd, buf, sizeof(buf));
11742 color_bitmap = strtoull(buf, NULL, 16);
11743
11744 *numColorReturned = 0;
11745 for (int i = 0; i < maxNumberColors; i++) {
11746 if (color_bitmap & 1) {
11747 colorList[*numColorReturned] = i;
11748 (*numColorReturned) += 1;
11749 }
11750 color_bitmap >>= 1;
11751 }
developer3cc61d12022-09-13 16:36:05 +080011752 return RETURN_OK;
11753}
11754
developer06a01d92022-09-07 16:32:39 +080011755/* multi-psk support */
11756INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11757{
11758 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011759 char interface_name[16] = {0};
11760
developerac6f1142022-12-20 19:26:35 +080011761 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011762 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011763
developerd946fd62022-12-08 18:03:28 +080011764 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11765 interface_name,
developer06a01d92022-09-07 16:32:39 +080011766 mac[0],
11767 mac[1],
11768 mac[2],
11769 mac[3],
11770 mac[4],
11771 mac[5]
11772 );
11773 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11774 _syscmd(cmd, key->wifi_keyId, 64);
11775
11776
11777 return RETURN_OK;
11778}
11779
11780INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11781{
developerd946fd62022-12-08 18:03:28 +080011782 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011783 FILE *fd = NULL;
11784 char fname[100];
11785 char cmd[128] = {0};
11786 char out[64] = {0};
11787 wifi_key_multi_psk_t * key = NULL;
11788 if(keysNumber < 0)
11789 return RETURN_ERR;
11790
developer431128d2022-12-16 15:30:41 +080011791 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011792 fd = fopen(fname, "w");
11793 if (!fd) {
11794 return RETURN_ERR;
11795 }
11796 key= (wifi_key_multi_psk_t *) keys;
11797 for(int i=0; i<keysNumber; ++i, key++) {
11798 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11799 }
11800 fclose(fd);
11801
11802 //reload file
developerac6f1142022-12-20 19:26:35 +080011803 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011804 return RETURN_ERR;
11805 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011806 _syscmd(cmd, out, 64);
11807 return RETURN_OK;
11808}
11809
11810INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11811{
11812 FILE *fd = NULL;
11813 char fname[100];
11814 char * line = NULL;
11815 char * pos = NULL;
11816 size_t len = 0;
11817 ssize_t read = 0;
11818 INT ret = RETURN_OK;
11819 wifi_key_multi_psk_t *keys_it = NULL;
11820
11821 if (keysNumber < 1) {
11822 return RETURN_ERR;
11823 }
11824
developer431128d2022-12-16 15:30:41 +080011825 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011826 fd = fopen(fname, "r");
11827 if (!fd) {
11828 return RETURN_ERR;
11829 }
11830
11831 if (keys == NULL) {
11832 ret = RETURN_ERR;
11833 goto close;
11834 }
11835
11836 keys_it = keys;
11837 while ((read = getline(&line, &len, fd)) != -1) {
11838 //Strip trailing new line if present
11839 if (read > 0 && line[read-1] == '\n') {
11840 line[read-1] = '\0';
11841 }
11842
11843 if(strcmp(line,"keyid=")) {
11844 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11845 if (!(pos = index(line, ' '))) {
11846 ret = RETURN_ERR;
11847 goto close;
11848 }
11849 pos++;
11850 //Here should be 00:00:00:00:00:00
11851 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11852 printf("Not supported MAC: %s\n", pos);
11853 }
11854 if (!(pos = index(pos, ' '))) {
11855 ret = RETURN_ERR;
11856 goto close;
11857 }
11858 pos++;
11859
11860 //The rest is PSK
11861 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11862 keys_it++;
11863
11864 if(--keysNumber <= 0)
11865 break;
11866 }
11867 }
11868
11869close:
11870 free(line);
11871 fclose(fd);
11872 return ret;
11873}
11874/* end of multi-psk support */
11875
11876INT wifi_setNeighborReports(UINT apIndex,
11877 UINT numNeighborReports,
11878 wifi_NeighborReport_t *neighborReports)
11879{
11880 char cmd[256] = { 0 };
11881 char hex_bssid[13] = { 0 };
11882 char bssid[18] = { 0 };
11883 char nr[256] = { 0 };
11884 char ssid[256];
11885 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011886 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011887 INT ret;
11888
11889 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011890 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011891 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011892 return RETURN_ERR;
11893 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 +080011894 system(cmd);
11895
11896 for(unsigned int i = 0; i < numNeighborReports; i++)
11897 {
11898 memset(ssid, 0, sizeof(ssid));
11899 ret = wifi_getSSIDName(apIndex, ssid);
11900 if (ret != RETURN_OK)
11901 return RETURN_ERR;
11902
11903 memset(hex_ssid, 0, sizeof(hex_ssid));
11904 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11905 sprintf(hex_ssid + k,"%02x", ssid[j]);
11906
11907 snprintf(hex_bssid, sizeof(hex_bssid),
11908 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11909 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11910 snprintf(bssid, sizeof(bssid),
11911 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11912 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11913
11914 snprintf(nr, sizeof(nr),
11915 "%s" // bssid
11916 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11917 "%02hhx" // operclass
11918 "%02hhx" // channel
11919 "%02hhx", // phy_mode
11920 hex_bssid,
11921 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11922 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11923 neighborReports[i].opClass,
11924 neighborReports[i].channel,
11925 neighborReports[i].phyTable);
11926
11927 snprintf(cmd, sizeof(cmd),
11928 "hostapd_cli set_neighbor "
11929 "%s " // bssid
11930 "ssid=%s " // ssid
11931 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011932 "-i %s",
11933 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011934
11935 if (WEXITSTATUS(system(cmd)) != 0)
11936 {
11937 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11938 }
11939 }
11940
11941 return RETURN_OK;
11942}
11943
11944INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11945{
11946 return RETURN_OK;
11947}
11948
11949#ifdef _WIFI_HAL_TEST_
11950int main(int argc,char **argv)
11951{
11952 int index;
11953 INT ret=0;
11954 char buf[1024]="";
11955
11956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11957 if(argc<3)
11958 {
11959 if(argc==2)
11960 {
11961 if(!strcmp(argv[1], "init"))
11962 return wifi_init();
11963 if(!strcmp(argv[1], "reset"))
11964 return wifi_reset();
11965 if(!strcmp(argv[1], "wifi_getHalVersion"))
11966 {
11967 char buffer[64];
11968 if(wifi_getHalVersion(buffer)==RETURN_OK)
11969 printf("Version: %s\n", buffer);
11970 else
11971 printf("Error in wifi_getHalVersion\n");
11972 return RETURN_OK;
11973 }
11974 }
11975 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11976 exit(-1);
11977 }
11978
11979 index = atoi(argv[2]);
11980 if(strstr(argv[1], "wifi_getApName")!=NULL)
11981 {
11982 wifi_getApName(index,buf);
11983 printf("Ap name is %s \n",buf);
11984 return 0;
11985 }
11986 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11987 {
11988 BOOL b = FALSE;
11989 BOOL *output_bool = &b;
11990 wifi_getRadioAutoChannelEnable(index,output_bool);
11991 printf("Channel enabled = %d \n",b);
11992 return 0;
11993 }
11994 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11995 {
11996 wifi_getApWpaEncryptionMode(index,buf);
11997 printf("encryption enabled = %s\n",buf);
11998 return 0;
11999 }
12000 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
12001 {
12002 BOOL b = FALSE;
12003 BOOL *output_bool = &b;
12004 wifi_getApSsidAdvertisementEnable(index,output_bool);
12005 printf("advertisment enabled = %d\n",b);
12006 return 0;
12007 }
12008 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
12009 {
12010 if(argc <= 3 )
12011 {
12012 printf("Insufficient arguments \n");
12013 exit(-1);
12014 }
12015
12016 char sta[20] = {'\0'};
12017 ULLONG handle= 0;
12018 strcpy(sta,argv[3]);
12019 mac_address_t st;
12020 mac_addr_aton(st,sta);
12021
12022 wifi_associated_dev_tid_stats_t tid_stats;
12023 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12024 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12025 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);
12026 }
12027
12028 if(strstr(argv[1], "getApEnable")!=NULL) {
12029 BOOL enable;
12030 ret=wifi_getApEnable(index, &enable);
12031 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12032 }
12033 else if(strstr(argv[1], "setApEnable")!=NULL) {
12034 BOOL enable = atoi(argv[3]);
12035 ret=wifi_setApEnable(index, enable);
12036 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12037 }
12038 else if(strstr(argv[1], "getApStatus")!=NULL) {
12039 char status[64];
12040 ret=wifi_getApStatus(index, status);
12041 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
12042 }
12043 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
12044 {
12045 wifi_getSSIDNameStatus(index,buf);
12046 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
12047 return 0;
12048 }
12049 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
12050 wifi_ssidTrafficStats2_t stats={0};
12051 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
12052 printf("%s %d: returns %d\n", argv[1], index, ret);
12053 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
12054 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
12055 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
12056 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
12057 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
12058 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
12059 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
12060 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
12061 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
12062 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
12063 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
12064 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
12065 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
12066 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
12067 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
12068 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
12069 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
12070 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
12071 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
12072 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
12073 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
12074 }
12075 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
12076 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
12077 UINT array_size=0;
12078 UINT i=0;
12079 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
12080 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12081 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
12082 printf(" neighbor %d:\n", i);
12083 printf(" ap_SSID =%s\n", pt->ap_SSID);
12084 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
12085 printf(" ap_Mode =%s\n", pt->ap_Mode);
12086 printf(" ap_Channel =%d\n", pt->ap_Channel);
12087 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
12088 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12089 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
12090 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
12091 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
12092 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
12093 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12094 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
12095 printf(" ap_Noise =%d\n", pt->ap_Noise);
12096 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
12097 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
12098 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
12099 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
12100 }
12101 if(neighbor_ap_array)
12102 free(neighbor_ap_array); //make sure to free the list
12103 }
12104 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
12105 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
12106 UINT array_size=0;
12107 UINT i=0;
12108 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
12109 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12110 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
12111 printf(" associated_dev %d:\n", i);
12112 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
12113 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
12114 printf(" cli_SNR =%d\n", pt->cli_SNR);
12115 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
12116 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
12117 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
12118 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
12119 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
12120 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
12121 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
12122 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
12123 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
12124 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
12125 }
12126 if(associated_dev_array)
12127 free(associated_dev_array); //make sure to free the list
12128 }
12129
12130 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12131 {
12132#define MAX_ARRAY_SIZE 64
12133 int i, array_size;
12134 char *p, *ch_str;
12135 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12136
12137 if(argc != 5)
12138 {
12139 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12140 exit(-1);
12141 }
12142 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12143
12144 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12145 {
12146 strtok_r(ch_str, ",", &p);
12147 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12148 }
12149 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12150 if(!array_size)
12151 array_size=1;//Need to print current channel statistics
12152 for(i=0; i<array_size; i++)
12153 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12154 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12155 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12156 input_output_channelStats_array[i].ch_number,\
12157 input_output_channelStats_array[i].ch_noise,\
12158 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12159 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12160 input_output_channelStats_array[i].ch_utilization_busy,\
12161 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12162 input_output_channelStats_array[i].ch_utilization_total);
12163 }
12164
12165 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12166 {
12167 if(argc <= 3 )
12168 {
12169 printf("Insufficient arguments \n");
12170 exit(-1);
12171 }
12172 char mac_addr[20] = {'\0'};
12173 wifi_device_t output_struct;
12174 int dev_index = atoi(argv[3]);
12175
12176 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12177 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12178 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);
12179 }
12180
12181 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12182 {
12183 if (argc <= 3)
12184 {
12185 printf("Insufficient arguments\n");
12186 exit(-1);
12187 }
12188 char args[256];
12189 wifi_NeighborReport_t *neighborReports;
12190
12191 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12192 if (!neighborReports)
12193 {
12194 printf("Failed to allocate memory");
12195 exit(-1);
12196 }
12197
12198 for (int i = 3; i < argc; ++i)
12199 {
12200 char *val;
12201 int j = 0;
12202 memset(args, 0, sizeof(args));
12203 strncpy(args, argv[i], sizeof(args));
12204 val = strtok(args, ";");
12205 while (val != NULL)
12206 {
12207 if (j == 0)
12208 {
12209 mac_addr_aton(neighborReports[i - 3].bssid, val);
12210 } else if (j == 1)
12211 {
12212 neighborReports[i - 3].info = strtol(val, NULL, 16);
12213 } else if (j == 2)
12214 {
12215 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12216 } else if (j == 3)
12217 {
12218 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12219 } else if (j == 4)
12220 {
12221 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12222 } else {
12223 printf("Insufficient arguments]n\n");
12224 exit(-1);
12225 }
12226 val = strtok(NULL, ";");
12227 j++;
12228 }
12229 }
12230
12231 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12232 if (ret != RETURN_OK)
12233 {
12234 printf("wifi_setNeighborReports ret = %d", ret);
12235 exit(-1);
12236 }
12237 }
12238 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12239 {
12240 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12241 printf("%s.\n", buf);
12242 else
12243 printf("Error returned\n");
12244 }
12245 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12246 {
12247 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12248 printf("%s.\n", buf);
12249 else
12250 printf("Error returned\n");
12251 }
12252 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12253 {
12254 if (argc <= 2)
12255 {
12256 printf("Insufficient arguments\n");
12257 exit(-1);
12258 }
12259 char buf[64]= {'\0'};
12260 wifi_getRadioOperatingChannelBandwidth(index,buf);
12261 printf("Current bandwidth is %s \n",buf);
12262 return 0;
12263 }
12264 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12265 {
12266 if (argc <= 5)
12267 {
12268 printf("Insufficient arguments\n");
12269 exit(-1);
12270 }
12271 UINT channel = atoi(argv[3]);
12272 UINT width = atoi(argv[4]);
12273 UINT beacon = atoi(argv[5]);
12274 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12275 printf("Result = %d", ret);
12276 }
12277
12278 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12279 return 0;
12280}
12281
12282#endif
12283
12284#ifdef WIFI_HAL_VERSION_3
12285
developer1e5aa162022-09-13 16:06:24 +080012286INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12287{
12288 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12289 if (bitMap & WIFI_BITRATE_1MBPS)
12290 strcat(BasicRate, "1,");
12291 if (bitMap & WIFI_BITRATE_2MBPS)
12292 strcat(BasicRate, "2,");
12293 if (bitMap & WIFI_BITRATE_5_5MBPS)
12294 strcat(BasicRate, "5.5,");
12295 if (bitMap & WIFI_BITRATE_6MBPS)
12296 strcat(BasicRate, "6,");
12297 if (bitMap & WIFI_BITRATE_9MBPS)
12298 strcat(BasicRate, "9,");
12299 if (bitMap & WIFI_BITRATE_11MBPS)
12300 strcat(BasicRate, "11,");
12301 if (bitMap & WIFI_BITRATE_12MBPS)
12302 strcat(BasicRate, "12,");
12303 if (bitMap & WIFI_BITRATE_18MBPS)
12304 strcat(BasicRate, "18,");
12305 if (bitMap & WIFI_BITRATE_24MBPS)
12306 strcat(BasicRate, "24,");
12307 if (bitMap & WIFI_BITRATE_36MBPS)
12308 strcat(BasicRate, "36,");
12309 if (bitMap & WIFI_BITRATE_48MBPS)
12310 strcat(BasicRate, "48,");
12311 if (bitMap & WIFI_BITRATE_54MBPS)
12312 strcat(BasicRate, "54,");
12313 if (strlen(BasicRate) != 0) // remove last comma
12314 BasicRate[strlen(BasicRate) - 1] = '\0';
12315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12316 return RETURN_OK;
12317}
12318
12319INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12320{
12321 UINT BitMap = 0;
12322 char *rate;
12323
12324 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12325 rate = strtok(BasicRatesList, ",");
12326 while(rate != NULL)
12327 {
12328 if (strcmp(rate, "1") == 0)
12329 BitMap |= WIFI_BITRATE_1MBPS;
12330 else if (strcmp(rate, "2") == 0)
12331 BitMap |= WIFI_BITRATE_2MBPS;
12332 else if (strcmp(rate, "5.5") == 0)
12333 BitMap |= WIFI_BITRATE_5_5MBPS;
12334 else if (strcmp(rate, "6") == 0)
12335 BitMap |= WIFI_BITRATE_6MBPS;
12336 else if (strcmp(rate, "9") == 0)
12337 BitMap |= WIFI_BITRATE_9MBPS;
12338 else if (strcmp(rate, "11") == 0)
12339 BitMap |= WIFI_BITRATE_11MBPS;
12340 else if (strcmp(rate, "12") == 0)
12341 BitMap |= WIFI_BITRATE_12MBPS;
12342 else if (strcmp(rate, "18") == 0)
12343 BitMap |= WIFI_BITRATE_18MBPS;
12344 else if (strcmp(rate, "24") == 0)
12345 BitMap |= WIFI_BITRATE_24MBPS;
12346 else if (strcmp(rate, "36") == 0)
12347 BitMap |= WIFI_BITRATE_36MBPS;
12348 else if (strcmp(rate, "48") == 0)
12349 BitMap |= WIFI_BITRATE_48MBPS;
12350 else if (strcmp(rate, "54") == 0)
12351 BitMap |= WIFI_BITRATE_54MBPS;
12352 rate = strtok(NULL, ",");
12353 }
12354 *basicRateBitMap = BitMap;
12355 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12356 return RETURN_OK;
12357}
12358
developer7c4cd202023-03-01 10:56:29 +080012359INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12360{
12361 int center_channel = 0;
12362 char central_channel_str[16] = {0};
12363 char config_file[32] = {0};
12364 struct params param = {0};
12365
12366 center_channel = util_unii_6g_centerfreq("HT320", channel);
12367 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12368 if (channel >= 193)
12369 return RETURN_ERR;
12370 if (channel >= 33) {
12371 if (channel > center_channel)
12372 center_channel += 32;
12373 else
12374 center_channel -= 32;
12375 }
12376 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12377 if (channel <= 29)
12378 return RETURN_ERR;
12379 }
12380 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12381 param.name = "eht_oper_centr_freq_seg0_idx";
12382 param.value = central_channel_str;
12383 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12384 wifi_hostapdWrite(config_file, &param, 1);
12385
12386 return RETURN_OK;
12387}
12388
12389INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12390{
12391 int op_class = 0;
12392 char config_file[32] = {0};
12393 char op_class_str[8] = {0};
12394 struct params param = {0};
12395
12396 if (bandwidth == 20)
12397 op_class = 131;
12398 else if (bandwidth == 40)
12399 op_class = 132;
12400 else if (bandwidth == 80)
12401 op_class = 133;
12402 else if (bandwidth == 160)
12403 op_class = 134;
12404 else if (bandwidth == 320)
12405 op_class = 137;
12406 else
12407 return RETURN_ERR;
12408 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12409 param.name = "op_class";
12410 param.value = op_class_str;
12411 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12412 wifi_hostapdWrite(config_file, &param, 1);
12413 return RETURN_OK;
12414}
12415
12416INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12417{
12418 char config_file[32] = {0};
12419 char buf [16] = {0};
12420
12421 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12422 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12423 return RETURN_ERR; // 6g band should set op_class
12424 *class = (UINT)strtoul(buf, NULL, 10);
12425
12426 return RETURN_OK;
12427}
12428
developer1e5aa162022-09-13 16:06:24 +080012429// 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 +080012430INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12431{
developer1e5aa162022-09-13 16:06:24 +080012432 char buf[128] = {0};
12433 char cmd[128] = {0};
12434 char config_file[64] = {0};
12435 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012436 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012437 wifi_radio_operationParam_t current_param;
12438
12439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12440
12441 multiple_set = TRUE;
12442 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12443 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12444 return RETURN_ERR;
12445 }
12446 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12447 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12448 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12449 return RETURN_ERR;
12450 }
12451 }
developer5884e982022-10-06 10:52:50 +080012452
12453 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12454 bandwidth = 20;
12455 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12456 bandwidth = 40;
12457 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12458 bandwidth = 80;
12459 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12460 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012461 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12462 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012463 if (operationParam->autoChannelEnabled){
12464 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12465 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12466 return RETURN_ERR;
12467 }
12468 }else{
developer1e5aa162022-09-13 16:06:24 +080012469 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12470 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12471 return RETURN_ERR;
12472 }
12473 }
developer5884e982022-10-06 10:52:50 +080012474
developer7c4cd202023-03-01 10:56:29 +080012475 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12476 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12477 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12478 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12479 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12480 return RETURN_ERR;
12481 }
12482 }
12483
12484 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12485 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12486 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12487 return RETURN_ERR;
12488 }
12489 }
12490
developer1e5aa162022-09-13 16:06:24 +080012491 if (current_param.variant != operationParam->variant) {
12492 // Two different definition bit map, so need to check every bit.
12493 if (operationParam->variant & WIFI_80211_VARIANT_A)
12494 set_mode |= WIFI_MODE_A;
12495 if (operationParam->variant & WIFI_80211_VARIANT_B)
12496 set_mode |= WIFI_MODE_B;
12497 if (operationParam->variant & WIFI_80211_VARIANT_G)
12498 set_mode |= WIFI_MODE_G;
12499 if (operationParam->variant & WIFI_80211_VARIANT_N)
12500 set_mode |= WIFI_MODE_N;
12501 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12502 set_mode |= WIFI_MODE_AC;
12503 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12504 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012505 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12506 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012507 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12508 memset(buf, 0, sizeof(buf));
12509 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12510 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12511 return RETURN_ERR;
12512 }
12513 }
12514 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12515 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12516 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12517 return RETURN_ERR;
12518 }
12519 }
12520 if (current_param.beaconInterval != operationParam->beaconInterval) {
12521 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12522 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12523 return RETURN_ERR;
12524 }
12525 }
12526 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12527 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12528 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12529 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12530 return RETURN_ERR;
12531 }
12532 }
12533 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12534 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12535 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12536 return RETURN_ERR;
12537 }
12538 }
12539 if (current_param.guardInterval != operationParam->guardInterval) {
12540 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12541 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12542 return RETURN_ERR;
12543 }
12544 }
12545 if (current_param.transmitPower != operationParam->transmitPower) {
12546 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12547 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12548 return RETURN_ERR;
12549 }
12550 }
12551 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12552 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12553 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12554 return RETURN_ERR;
12555 }
12556 }
12557 if (current_param.obssCoex != operationParam->obssCoex) {
12558 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12559 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12560 return RETURN_ERR;
12561 }
12562 }
12563 if (current_param.stbcEnable != operationParam->stbcEnable) {
12564 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12565 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12566 return RETURN_ERR;
12567 }
12568 }
developer5735d092023-09-19 20:12:26 +080012569 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12570 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12571 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12572 return RETURN_ERR;
12573 }
12574 }
developer1e5aa162022-09-13 16:06:24 +080012575
12576 // if enable is true, then restart the radio
12577 wifi_setRadioEnable(index, FALSE);
12578 if (operationParam->enable == TRUE)
12579 wifi_setRadioEnable(index, TRUE);
12580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12581
developer06a01d92022-09-07 16:32:39 +080012582 return RETURN_OK;
12583}
12584
12585INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12586{
developer1e5aa162022-09-13 16:06:24 +080012587 char band[64] = {0};
12588 char buf[256] = {0};
12589 char config_file[64] = {0};
12590 char cmd[128] = {0};
12591 int ret = RETURN_ERR;
12592 int mode = 0;
12593 ULONG channel = 0;
12594 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012595
12596 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12597 printf("Entering %s index = %d\n", __func__, (int)index);
12598
developer1e5aa162022-09-13 16:06:24 +080012599 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12600 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12601 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012602 {
developer1e5aa162022-09-13 16:06:24 +080012603 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012604 return RETURN_ERR;
12605 }
12606 operationParam->enable = enabled;
12607
12608 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012609 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012610 {
developer1e5aa162022-09-13 16:06:24 +080012611 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012612 return RETURN_ERR;
12613 }
12614
12615 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012616 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012617 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012618 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012619 else if (!strcmp(band, "6GHz"))
12620 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012621 else
12622 {
developer1e5aa162022-09-13 16:06:24 +080012623 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012624 band);
12625 }
12626
developer1e5aa162022-09-13 16:06:24 +080012627 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12628 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12629 operationParam->channel = 0;
12630 operationParam->autoChannelEnabled = TRUE;
12631 } else {
12632 operationParam->channel = strtol(buf, NULL, 10);
12633 operationParam->autoChannelEnabled = FALSE;
12634 }
12635
developer06a01d92022-09-07 16:32:39 +080012636 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012637 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12638 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12639 return RETURN_ERR;
12640 }
developer06a01d92022-09-07 16:32:39 +080012641 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12642 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12643 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012644 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012645 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12646 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012647 else
12648 {
developer1e5aa162022-09-13 16:06:24 +080012649 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12650 return false;
developer06a01d92022-09-07 16:32:39 +080012651 }
12652
developer7c4cd202023-03-01 10:56:29 +080012653 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12654 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12655 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12656 return RETURN_ERR;
12657 }
12658 }
12659
developer1e5aa162022-09-13 16:06:24 +080012660 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12661 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12662 return RETURN_ERR;
12663 }
12664 // Two different definition bit map, so need to check every bit.
12665 if (mode & WIFI_MODE_A)
12666 operationParam->variant |= WIFI_80211_VARIANT_A;
12667 if (mode & WIFI_MODE_B)
12668 operationParam->variant |= WIFI_80211_VARIANT_B;
12669 if (mode & WIFI_MODE_G)
12670 operationParam->variant |= WIFI_80211_VARIANT_G;
12671 if (mode & WIFI_MODE_N)
12672 operationParam->variant |= WIFI_80211_VARIANT_N;
12673 if (mode & WIFI_MODE_AC)
12674 operationParam->variant |= WIFI_80211_VARIANT_AC;
12675 if (mode & WIFI_MODE_AX)
12676 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012677 if (mode & WIFI_MODE_BE)
12678 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012679 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12680 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12681 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012682 }
developer1e5aa162022-09-13 16:06:24 +080012683 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12684 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12685 return RETURN_ERR;
12686 }
12687 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12688 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12689 return RETURN_ERR;
12690 }
developer06a01d92022-09-07 16:32:39 +080012691
developer1e5aa162022-09-13 16:06:24 +080012692 memset(buf, 0, sizeof(buf));
12693 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12694 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12695 return RETURN_ERR;
12696 }
12697 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12698
12699 memset(buf, 0, sizeof(buf));
12700 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12701 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12702 return RETURN_ERR;
12703 }
12704 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12705
12706 memset(buf, 0, sizeof(buf));
12707 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12708 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12709
12710 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12711 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12712 return RETURN_ERR;
12713 }
12714 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12715 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12716 return RETURN_ERR;
12717 }
12718
12719 memset(buf, 0, sizeof(buf));
12720 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12721 if (strcmp(buf, "-1") == 0) {
12722 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12723 operationParam->ctsProtection = FALSE;
12724 } else {
12725 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12726 operationParam->ctsProtection = TRUE;
12727 }
12728
12729 memset(buf, 0, sizeof(buf));
12730 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12731 if (strcmp(buf, "0") == 0)
12732 operationParam->obssCoex = FALSE;
12733 else
12734 operationParam->obssCoex = TRUE;
12735
12736 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12737 _syscmd(cmd, buf, sizeof(buf));
12738 if (strlen(buf) != 0)
12739 operationParam->stbcEnable = TRUE;
12740 else
12741 operationParam->stbcEnable = FALSE;
12742
developer5735d092023-09-19 20:12:26 +080012743 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12744 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12745 return RETURN_ERR;
12746 }
developer1e5aa162022-09-13 16:06:24 +080012747
12748 // Below value is hardcoded
12749
12750 operationParam->numSecondaryChannels = 0;
12751 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12752 operationParam->channelSecondary[i] = 0;
12753 }
12754 operationParam->csa_beacon_count = 15;
12755 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012756
12757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12758 return RETURN_OK;
12759}
12760
12761static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12762{
developerc086fb72022-10-04 10:18:22 +080012763 int max_radio_num = 0;
12764
12765 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012766 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012767 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12768 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012769 }
12770
developerc086fb72022-10-04 10:18:22 +080012771 return (arrayIndex * max_radio_num) + radioIndex;
12772}
developer06a01d92022-09-07 16:32:39 +080012773
developerc086fb72022-10-04 10:18:22 +080012774wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12775 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12776 return WIFI_BITRATE_1MBPS;
12777 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12778 return WIFI_BITRATE_2MBPS;
12779 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12780 return WIFI_BITRATE_5_5MBPS;
12781 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12782 return WIFI_BITRATE_6MBPS;
12783 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12784 return WIFI_BITRATE_9MBPS;
12785 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12786 return WIFI_BITRATE_11MBPS;
12787 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12788 return WIFI_BITRATE_12MBPS;
12789 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12790 return WIFI_BITRATE_18MBPS;
12791 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12792 return WIFI_BITRATE_24MBPS;
12793 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12794 return WIFI_BITRATE_36MBPS;
12795 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12796 return WIFI_BITRATE_48MBPS;
12797 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12798 return WIFI_BITRATE_54MBPS;
12799 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012800}
12801
developer1d57d002022-10-12 18:03:15 +080012802INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12803{
12804 if (beacon == WIFI_BITRATE_1MBPS)
12805 strcpy(beacon_str, "1Mbps");
12806 else if (beacon == WIFI_BITRATE_2MBPS)
12807 strcpy(beacon_str, "2Mbps");
12808 else if (beacon == WIFI_BITRATE_5_5MBPS)
12809 strcpy(beacon_str, "5.5Mbps");
12810 else if (beacon == WIFI_BITRATE_6MBPS)
12811 strcpy(beacon_str, "6Mbps");
12812 else if (beacon == WIFI_BITRATE_9MBPS)
12813 strcpy(beacon_str, "9Mbps");
12814 else if (beacon == WIFI_BITRATE_11MBPS)
12815 strcpy(beacon_str, "11Mbps");
12816 else if (beacon == WIFI_BITRATE_12MBPS)
12817 strcpy(beacon_str, "12Mbps");
12818 else if (beacon == WIFI_BITRATE_18MBPS)
12819 strcpy(beacon_str, "18Mbps");
12820 else if (beacon == WIFI_BITRATE_24MBPS)
12821 strcpy(beacon_str, "24Mbps");
12822 else if (beacon == WIFI_BITRATE_36MBPS)
12823 strcpy(beacon_str, "36Mbps");
12824 else if (beacon == WIFI_BITRATE_48MBPS)
12825 strcpy(beacon_str, "48Mbps");
12826 else if (beacon == WIFI_BITRATE_54MBPS)
12827 strcpy(beacon_str, "54Mbps");
12828 return RETURN_OK;
12829}
12830
developer74ed4192023-09-21 17:15:17 +080012831void checkVapStatus(int apIndex, bool *enable)
12832{
12833 char if_name[16] = {0};
12834 char cmd[128] = {0};
12835 char buf[128] = {0};
12836
12837 *enable = FALSE;
12838 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12839 return;
12840
12841 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12842 _syscmd(cmd, buf, sizeof(buf));
12843 if (strlen(buf) > 0)
12844 *enable = TRUE;
12845 return;
12846}
12847
developerefb790a2023-12-26 18:58:32 +080012848INT wifi_getVapInfoMisc(int vap_index)
12849{
12850 char config_file[MAX_BUF_SIZE] = {0};
12851
12852 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX,vap_index);
12853 wifi_hostapdRead(config_file,"ssid",vap_info[vap_index].ssid, MAX_BUF_SIZE);
12854 wifi_hostapdRead(config_file,"wpa", vap_info[vap_index].wpa, MAX_BUF_SIZE);
12855 wifi_hostapdRead(config_file,"wpa_key_mgmt", vap_info[vap_index].wpa_key_mgmt, MAX_BUF_SIZE);
12856 wifi_hostapdRead(config_file,"wpa_passphrase", vap_info[vap_index].wpa_passphrase, MAX_BUF_SIZE);
12857 wifi_hostapdRead(config_file,"ap_isolate", vap_info[vap_index].ap_isolate, MAX_BUF_SIZE);
12858 wifi_hostapdRead(config_file,"macaddr_acl", vap_info[vap_index].macaddr_acl, MAX_BUF_SIZE);
12859 wifi_hostapdRead(config_file,"bss_transition", vap_info[vap_index].bss_transition, MAX_BUF_SIZE);
12860 wifi_hostapdRead(config_file,"ignore_broadcast_ssid", vap_info[vap_index].ignore_broadcast_ssid, MAX_BUF_SIZE);
12861 wifi_hostapdRead(config_file, "max_num_sta", vap_info[vap_index].max_sta, MAX_BUF_SIZE);
12862 return RETURN_OK;
12863}
12864
12865int wifi_Syncthread(void *arg)
12866{
12867 int radio_idx = 0, i = 0;
12868 int vap_index = 0;
developera2af46a2024-01-04 19:11:23 +080012869 int max_radio = 0;
developerefb790a2023-12-26 18:58:32 +080012870
developera2af46a2024-01-04 19:11:23 +080012871 wifi_getMaxRadioNumber(&max_radio);
developerefb790a2023-12-26 18:58:32 +080012872 while (1)
12873 {
12874 sleep(5);
developera2af46a2024-01-04 19:11:23 +080012875 for (radio_idx = 0; radio_idx < max_radio; radio_idx++)
developerefb790a2023-12-26 18:58:32 +080012876 {
12877 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
12878 {
12879 vap_index = array_index_to_vap_index(radio_idx, i);
12880 if (vap_index >= 0)
12881 wifi_getVapInfoMisc(vap_index);
12882 }
12883 }
12884 syn_flag = 1;
12885 }
12886 return 0;
12887}
12888
developer06a01d92022-09-07 16:32:39 +080012889INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12890{
developerc086fb72022-10-04 10:18:22 +080012891 INT mode = 0;
12892 INT ret = -1;
12893 INT output = 0;
12894 int i = 0;
12895 int vap_index = 0;
12896 BOOL enabled = FALSE;
12897 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012898 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012899
developer06a01d92022-09-07 16:32:39 +080012900
12901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12902 printf("Entering %s index = %d\n", __func__, (int)index);
12903
developera77d84b2023-02-22 16:10:50 +080012904 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012905 {
developerc086fb72022-10-04 10:18:22 +080012906 map->vap_array[i].radio_index = index;
12907
developer06a01d92022-09-07 16:32:39 +080012908 vap_index = array_index_to_vap_index(index, i);
12909 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012910 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012911
developerc086fb72022-10-04 10:18:22 +080012912 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012913
12914 map->vap_array[i].vap_index = vap_index;
12915
12916 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012917 ret = wifi_getApName(vap_index, buf);
12918 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012919 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12920
developerc086fb72022-10-04 10:18:22 +080012921 return RETURN_ERR;
12922 }
12923 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12924
12925 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012926 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012927 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012928 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012929 return RETURN_ERR;
12930 }
12931 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 +080012932
developer74ed4192023-09-21 17:15:17 +080012933 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012934 map->vap_array[i].u.bss_info.enabled = enabled;
12935
developerc086fb72022-10-04 10:18:22 +080012936 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12937 if (ret != RETURN_OK) {
12938 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12939 return RETURN_ERR;
12940 }
developer06a01d92022-09-07 16:32:39 +080012941 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012942
12943 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12944 if (ret != RETURN_OK) {
12945 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12946 return RETURN_ERR;
12947 }
12948 map->vap_array[i].u.bss_info.isolation = enabled;
12949
12950 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12951 if (ret != RETURN_OK) {
12952 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12953 return RETURN_ERR;
12954 }
12955 map->vap_array[i].u.bss_info.bssMaxSta = output;
12956
12957 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12958 if (ret != RETURN_OK) {
12959 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12960 return RETURN_ERR;
12961 }
12962 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012963
developerc086fb72022-10-04 10:18:22 +080012964 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12965 if (ret != RETURN_OK) {
12966 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12967 return RETURN_ERR;
12968 }
12969 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012970
developerc086fb72022-10-04 10:18:22 +080012971 ret = wifi_getApSecurity(vap_index, &security);
12972 if (ret != RETURN_OK) {
12973 printf("%s: wifi_getApSecurity return error\n", __func__);
12974 return RETURN_ERR;
12975 }
12976 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012977
developerc086fb72022-10-04 10:18:22 +080012978 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12979 if (ret != RETURN_OK) {
12980 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12981 return RETURN_ERR;
12982 }
12983 if (mode == 0)
12984 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12985 else
12986 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12987 if (mode == 1)
12988 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12989 else if (mode == 2)
12990 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012991
developerc086fb72022-10-04 10:18:22 +080012992 ret = wifi_getApWmmEnable(vap_index, &enabled);
12993 if (ret != RETURN_OK) {
12994 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12995 return RETURN_ERR;
12996 }
12997 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012998
developerc086fb72022-10-04 10:18:22 +080012999 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
13000 if (ret != RETURN_OK) {
13001 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080013002 return RETURN_ERR;
13003 }
developerc086fb72022-10-04 10:18:22 +080013004 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080013005
13006 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080013007 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080013008 if (ret != RETURN_OK) {
13009 printf("%s: wifi_getApBeaconRate return error\n", __func__);
13010 return RETURN_ERR;
13011 }
13012 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080013013
developerc086fb72022-10-04 10:18:22 +080013014 memset(buf, 0, sizeof(buf));
13015 ret = wifi_getBaseBSSID(vap_index, buf);
13016 if (ret != RETURN_OK) {
13017 printf("%s: wifi_getBaseBSSID return error\n", __func__);
13018 return RETURN_ERR;
13019 }
13020 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13021 &map->vap_array[i].u.bss_info.bssid[0],
13022 &map->vap_array[i].u.bss_info.bssid[1],
13023 &map->vap_array[i].u.bss_info.bssid[2],
13024 &map->vap_array[i].u.bss_info.bssid[3],
13025 &map->vap_array[i].u.bss_info.bssid[4],
13026 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080013027 // 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]);
13028
13029 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
13030 if (ret != RETURN_OK) {
13031 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
13032 return RETURN_ERR;
13033 }
13034 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080013035
13036 ret = wifi_getApWpsEnable(vap_index, &enabled);
13037 if (ret != RETURN_OK) {
13038 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
13039 return RETURN_ERR;
13040 }
13041
13042 map->vap_array[i].u.bss_info.wps.enable = enabled;
13043
developera77d84b2023-02-22 16:10:50 +080013044 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080013045 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080013046 }
developerefb790a2023-12-26 18:58:32 +080013047
13048 if (!tflag) {
13049 result = pthread_create(&pthread_id, NULL, wifi_Syncthread,NULL);
13050 if (result != 0)
13051 printf("%s %d fail create sync thread\n", __func__, __LINE__);
13052 else
13053 tflag = 1;
13054 }
13055
developer06a01d92022-09-07 16:32:39 +080013056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13057 return RETURN_OK;
13058}
13059
developer431128d2022-12-16 15:30:41 +080013060
developerd946fd62022-12-08 18:03:28 +080013061static int prepareInterface(UINT apIndex, char *new_interface)
13062{
13063 char cur_interface[16] = {0};
13064 char config_file[128] = {0};
13065 char cmd[128] = {0};
13066 char buf[16] = {0};
13067 int max_radio_num = 0;
13068 int radioIndex = -1;
13069 int phyIndex = -1;
13070
13071 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13072 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13073
13074 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
13075 wifi_getMaxRadioNumber(&max_radio_num);
13076 radioIndex = apIndex % max_radio_num;
13077 phyIndex = radio_index_to_phy(radioIndex);
13078 // disable and del old interface, then add new interface
13079 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080013080 if (!(apIndex/max_radio_num)) {
13081 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
13082 _syscmd(cmd, buf, sizeof(buf));
13083 }
developerd946fd62022-12-08 18:03:28 +080013084 }
developer431128d2022-12-16 15:30:41 +080013085 // update the vap status file
13086 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13087 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080013088 return RETURN_OK;
13089}
13090
developer06a01d92022-09-07 16:32:39 +080013091INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13092{
developerd946fd62022-12-08 18:03:28 +080013093 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013094 unsigned int i;
13095 wifi_vap_info_t *vap_info = NULL;
13096 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080013097 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080013098 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080013099 char buf[256] = {0};
13100 char cmd[128] = {0};
13101 char config_file[64] = {0};
13102 char bssid[32] = {0};
13103 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080013104 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080013105
13106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13107 printf("Entering %s index = %d\n", __func__, (int)index);
13108 for (i = 0; i < map->num_vaps; i++)
13109 {
developer1d57d002022-10-12 18:03:15 +080013110 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080013111 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080013112
13113 // Check vap status file to enable multiple ap if the system boot.
13114 checkVapStatus(vap_info->vap_index, &enable);
13115 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080013116 continue;
developer06a01d92022-09-07 16:32:39 +080013117
developer1d57d002022-10-12 18:03:15 +080013118 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13119
developer431128d2022-12-16 15:30:41 +080013120 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13121 enable = FALSE;
13122
13123 // multi-ap first up need to copy current radio config
13124 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080013125 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13126 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080013127 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13128 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13129 } else {
13130 // Check whether the interface name is valid or this ap change it.
13131 int apIndex = -1;
13132 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13133 if (apIndex != -1 && apIndex != vap_info->vap_index)
13134 continue;
13135 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080013136 }
developer06a01d92022-09-07 16:32:39 +080013137
developer1d57d002022-10-12 18:03:15 +080013138 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080013139 params[0].name = "interface";
13140 params[0].value = vap_info->vap_name;
13141 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13142 params[1].name = "bssid";
13143 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080013144 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080013145 params[2].name = "wpa_psk_file";
13146 params[2].value = psk_file;
13147
13148 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13149 wifi_hostapdWrite(config_file, params, 3);
13150
13151 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13152 _syscmd(cmd, buf, sizeof(buf));
13153
13154 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13155 if (ret != RETURN_OK) {
13156 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13157 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013158 }
developer1d57d002022-10-12 18:03:15 +080013159
13160 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13161 if (ret != RETURN_OK) {
13162 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13163 return RETURN_ERR;
13164 }
13165
13166 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13167 if (ret != RETURN_OK) {
13168 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13169 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013170 }
13171
developer1d57d002022-10-12 18:03:15 +080013172 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13173 if (ret != RETURN_OK) {
13174 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13175 return RETURN_ERR;
13176 }
developer06a01d92022-09-07 16:32:39 +080013177
developer1d57d002022-10-12 18:03:15 +080013178 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13179 if (ret != RETURN_OK) {
13180 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13181 return RETURN_ERR;
13182 }
developer06a01d92022-09-07 16:32:39 +080013183
developer1d57d002022-10-12 18:03:15 +080013184 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13185 if (ret != RETURN_OK) {
13186 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13187 return RETURN_ERR;
13188 }
13189
developer804c64f2022-10-19 13:54:40 +080013190 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080013191 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080013192 }else {
13193 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080013194 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080013195 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13196 _syscmd(cmd, buf, sizeof(buf));
13197 }else{
developer1d57d002022-10-12 18:03:15 +080013198 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080013199 }
developer1d57d002022-10-12 18:03:15 +080013200 }
13201
13202 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13203 if (ret != RETURN_OK) {
13204 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13205 return RETURN_ERR;
13206 }
13207
13208 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13209 if (ret != RETURN_OK) {
13210 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13211 return RETURN_ERR;
13212 }
13213
13214 memset(buf, 0, sizeof(buf));
13215 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13216 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
13217 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13218 if (ret != RETURN_OK) {
13219 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13220 return RETURN_ERR;
13221 }
13222
developer1d57d002022-10-12 18:03:15 +080013223 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13224 if (ret != RETURN_OK) {
13225 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13226 return RETURN_ERR;
13227 }
13228
13229 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13230 if (ret != RETURN_OK) {
13231 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13232 return RETURN_ERR;
13233 }
developer06a01d92022-09-07 16:32:39 +080013234
developer894affa2023-05-10 18:13:19 +080013235 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
13236 if (ret != RETURN_OK) {
13237 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
13238 return RETURN_ERR;
13239 }
13240
developer2f995fb2023-02-24 10:40:44 +080013241 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080013242 if (vap_info->u.bss_info.enabled == TRUE)
13243 wifi_setApEnable(vap_info->vap_index, TRUE);
13244
developer2f995fb2023-02-24 10:40:44 +080013245 multiple_set = FALSE;
13246
13247 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080013248 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080013249 // The set wps methods function should check whether wps is configured.
13250 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
13251 if (ret != RETURN_OK) {
13252 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
13253 return RETURN_ERR;
13254 }
13255 // wifi_setApWpsConfigMethodsEnabled only write to config.
13256 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13257 if (ret != RETURN_OK) {
13258 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13259 return RETURN_ERR;
13260 }
13261 }
developer2f995fb2023-02-24 10:40:44 +080013262
developer894affa2023-05-10 18:13:19 +080013263 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013264 }
developerfb09ba62023-06-09 17:03:21 +080013265
13266 // IGMP Snooping enable should be placed after all hostapd_reload.
13267 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13268 if (ret != RETURN_OK) {
13269 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13270 return RETURN_ERR;
13271 }
13272
developer06a01d92022-09-07 16:32:39 +080013273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13274 return RETURN_OK;
13275}
13276
13277int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13278{
13279 char *token, *next;
13280 const char s[2] = ",";
13281 int count =0;
13282
13283 /* get the first token */
13284 token = strtok_r(pchannels, s, &next);
13285
13286 /* walk through other tokens */
13287 while( token != NULL && count < MAX_CHANNELS) {
13288 chlistptr->channels_list[count++] = atoi(token);
13289 token = strtok_r(NULL, s, &next);
13290 }
13291
13292 return count;
13293}
13294
13295static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13296{
13297 INT status;
13298 wifi_channels_list_t *chlistp;
13299 CHAR output_string[64];
13300 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013301 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013302 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013303
13304 if(rcap == NULL)
13305 {
13306 return RETURN_ERR;
13307 }
13308
13309 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013310 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013311
developer1e5aa162022-09-13 16:06:24 +080013312 if (band == band_2_4)
13313 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13314 else if (band == band_5)
13315 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13316 else if (band == band_6)
13317 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013318
13319 chlistp = &(rcap->channel_list[0]);
13320 memset(pchannels, 0, sizeof(pchannels));
13321
13322 /* possible number of radio channels */
13323 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13324 {
13325 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13326 }
13327 /* Number of channels and list*/
13328 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13329
13330 /* autoChannelSupported */
13331 /* always ON with wifi_getRadioAutoChannelSupported */
13332 rcap->autoChannelSupported = TRUE;
13333
13334 /* DCSSupported */
13335 /* always ON with wifi_getRadioDCSSupported */
13336 rcap->DCSSupported = TRUE;
13337
13338 /* zeroDFSSupported - TBD */
13339 rcap->zeroDFSSupported = FALSE;
13340
13341 /* Supported Country List*/
13342 memset(output_string, 0, sizeof(output_string));
13343 status = wifi_getRadioCountryCode(radioIndex, output_string);
13344 if( status != 0 ) {
13345 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13346 return RETURN_ERR;
13347 } else {
13348 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13349 }
13350 if(!strcmp(output_string,"US")){
13351 rcap->countrySupported[0] = wifi_countrycode_US;
13352 rcap->countrySupported[1] = wifi_countrycode_CA;
13353 } else if (!strcmp(output_string,"CA")) {
13354 rcap->countrySupported[0] = wifi_countrycode_CA;
13355 rcap->countrySupported[1] = wifi_countrycode_US;
13356 } else {
13357 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13358 }
13359
13360 rcap->numcountrySupported = 2;
13361
13362 /* csi */
13363 rcap->csi.maxDevices = 8;
13364 rcap->csi.soudingFrameSupported = TRUE;
13365
developer7930d352022-12-21 17:55:42 +080013366 wifi_GetInterfaceName(radioIndex, interface_name);
13367 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013368
13369 /* channelWidth - all supported bandwidths */
13370 int i=0;
13371 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013372
13373 /* mode - all supported variants */
13374 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13375 wifi_getRadioSupportedStandards(radioIndex, output_string);
13376
developer06a01d92022-09-07 16:32:39 +080013377 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13378 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13379 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013380 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013381
developer7c4cd202023-03-01 10:56:29 +080013382 if (strstr(output_string, "n") != NULL)
13383 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13384 if (strstr(output_string, "ax") != NULL)
13385 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13386 if (strstr(output_string, "be") != NULL)
13387 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13388 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013389 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13390 WIFI_CHANNELBANDWIDTH_40MHZ |
13391 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013392 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013393
developer7c4cd202023-03-01 10:56:29 +080013394 if (strstr(output_string, "n") != NULL)
13395 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13396 if (strstr(output_string, "ac") != NULL)
13397 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13398 if (strstr(output_string, "ax") != NULL)
13399 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13400 if (strstr(output_string, "be") != NULL)
13401 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13402 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13403 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13404 WIFI_CHANNELBANDWIDTH_40MHZ |
13405 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013406 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013407
13408 if (strstr(output_string, "be") != NULL) {
13409 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13410 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13411 }
developer06a01d92022-09-07 16:32:39 +080013412 }
developer7c4cd202023-03-01 10:56:29 +080013413
developer06a01d92022-09-07 16:32:39 +080013414 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13415 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13416
13417 /* supportedBitRate - all supported bitrates */
13418 rcap->supportedBitRate[i] = 0;
13419 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13420 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13421 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13422 }
developer1e5aa162022-09-13 16:06:24 +080013423 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013424 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13425 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13426 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13427 }
13428
13429
13430 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13431 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13432 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13433 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13434 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13435 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13436 rcap->cipherSupported = 0;
13437 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13438 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13439
13440 return RETURN_OK;
13441}
13442
13443INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13444{
developer30423732022-12-01 16:17:49 +080013445 INT status = 0, radioIndex = 0;
13446 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013447 int iter = 0;
developer30423732022-12-01 16:17:49 +080013448 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013449 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013450 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013451
13452 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13453
13454 memset(cap, 0, sizeof(wifi_hal_capability_t));
13455
13456 /* version */
13457 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13458 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13459
13460 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013461 wifi_getMaxRadioNumber(&max_num_radios);
13462 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013463
13464 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13465 {
13466 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13467 if (status != 0) {
13468 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13469 return RETURN_ERR;
13470 }
13471
13472 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13473 {
developer804c64f2022-10-19 13:54:40 +080013474 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013475 {
13476 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13477 return RETURN_ERR;
13478 }
13479 iface_info = &cap->wifi_prop.interface_map[iter];
13480 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13481 iface_info->rdk_radio_index = radioIndex;
13482 memset(output, 0, sizeof(output));
13483 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13484 {
13485 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13486 }
13487 // TODO: bridge name
13488 // TODO: vlan id
13489 // TODO: primary
13490 iface_info->index = array_index_to_vap_index(radioIndex, j);
13491 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013492 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013493 {
13494 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13495 }
13496 iter++;
13497 }
13498 }
13499
13500 cap->BandSteeringSupported = FALSE;
13501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13502 return RETURN_OK;
13503}
13504
developer9df4e652022-10-11 11:27:38 +080013505INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13506{
13507 struct params h_config={0};
13508 char config_file[64] = {0};
13509
13510 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13511
13512 h_config.name = "okc";
13513 h_config.value = okc_enable?"1":"0";
13514
13515 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13516 wifi_hostapdWrite(config_file, &h_config, 1);
13517 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13518
13519 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13520 return RETURN_OK;
13521}
13522
13523INT wifi_setSAEMFP(int ap_index, BOOL enable)
13524{
13525 struct params h_config={0};
13526 char config_file[64] = {0};
13527 char buf[128] = {0};
13528
13529 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13530
13531 h_config.name = "sae_require_mfp";
13532 h_config.value = enable?"1":"0";
13533
13534 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13535 wifi_hostapdWrite(config_file, &h_config, 1);
13536 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13537
13538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13539 return RETURN_OK;
13540}
13541
13542INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13543{
13544 struct params h_config={0};
13545 char config_file[64] = {0};
13546 char buf[128] = {0};
13547
13548 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13549
13550 h_config.name = "sae_pwe";
13551 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13552 h_config.value = buf;
13553
13554 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13555 wifi_hostapdWrite(config_file, &h_config, 1);
13556 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13557
13558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13559 return RETURN_OK;
13560}
13561
13562INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13563{
13564 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13565 struct params h_config={0};
13566 char config_file[64] = {0};
13567
13568 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13569
13570 h_config.name = "wpa_disable_eapol_key_retries";
13571 h_config.value = disable_EAPOL_retries?"1":"0";
13572
13573 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13574 wifi_hostapdWrite(config_file, &h_config, 1);
13575 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13576
13577 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13578 return RETURN_OK;
13579}
13580
developer06a01d92022-09-07 16:32:39 +080013581INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13582{
developer587c1b62022-09-27 15:58:59 +080013583 char buf[128] = {0};
13584 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013585 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013586 char password[64] = {0};
13587 char mfp[32] = {0};
13588 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013589 BOOL okc_enable = FALSE;
13590 BOOL sae_MFP = FALSE;
13591 BOOL disable_EAPOL_retries = TRUE;
13592 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013593 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013594 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013595
13596 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13597
13598 multiple_set = TRUE;
13599 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13600 if (security->mode == wifi_security_mode_none) {
13601 strcpy(wpa_mode, "None");
13602 } else if (security->mode == wifi_security_mode_wpa_personal)
13603 strcpy(wpa_mode, "WPA-Personal");
13604 else if (security->mode == wifi_security_mode_wpa2_personal)
13605 strcpy(wpa_mode, "WPA2-Personal");
13606 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13607 strcpy(wpa_mode, "WPA-WPA2-Personal");
13608 else if (security->mode == wifi_security_mode_wpa_enterprise)
13609 strcpy(wpa_mode, "WPA-Enterprise");
13610 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13611 strcpy(wpa_mode, "WPA2-Enterprise");
13612 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13613 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013614 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013615 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013616 okc_enable = TRUE;
13617 sae_MFP = TRUE;
13618 sae_pwe = 2;
13619 disable_EAPOL_retries = FALSE;
13620 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013621 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013622 okc_enable = TRUE;
13623 sae_MFP = TRUE;
13624 sae_pwe = 2;
13625 disable_EAPOL_retries = FALSE;
13626 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013627 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013628 sae_MFP = TRUE;
13629 sae_pwe = 2;
13630 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013631 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013632 strcpy(wpa_mode, "OWE");
13633 sae_MFP = TRUE;
13634 sae_pwe = 2;
13635 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013636 }
13637
13638 band = wifi_index_to_band(ap_index);
13639 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13640 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13641 return RETURN_ERR;
13642 }
developer587c1b62022-09-27 15:58:59 +080013643
13644 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013645 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013646 wifi_setSAEMFP(ap_index, sae_MFP);
13647 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013648 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013649
developerae432c62023-04-24 11:07:20 +080013650 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013651 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) {
13652 int key_len = strlen(security->u.key.key);
13653 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13654 if (key_len == 64) { // set wpa_psk
13655 strncpy(password, security->u.key.key, 64); // 64 characters
13656 password[64] = '\0';
13657 wifi_setApSecurityPreSharedKey(ap_index, password);
13658 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13659 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13660 strncpy(password, security->u.key.key, 63);
13661 password[63] = '\0';
13662 wifi_setApSecurityKeyPassphrase(ap_index, password);
13663 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13664 } else
13665 return RETURN_ERR;
13666 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013667 }
13668 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13669 params.name = "sae_password";
13670 params.value = security->u.key.key;
13671 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013672 } else { // remove sae_password
13673 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13674 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013675 }
13676 }
developer587c1b62022-09-27 15:58:59 +080013677
13678 if (security->mode != wifi_security_mode_none) {
13679 memset(&params, 0, sizeof(params));
13680 params.name = "wpa_pairwise";
13681 if (security->encr == wifi_encryption_tkip)
13682 params.value = "TKIP";
13683 else if (security->encr == wifi_encryption_aes)
13684 params.value = "CCMP";
13685 else if (security->encr == wifi_encryption_aes_tkip)
13686 params.value = "TKIP CCMP";
13687 wifi_hostapdWrite(config_file, &params, 1);
13688 }
13689
13690 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013691 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013692 else if (security->mfp == wifi_mfp_cfg_optional)
13693 strcpy(mfp, "Optional");
13694 else if (security->mfp == wifi_mfp_cfg_required)
13695 strcpy(mfp, "Required");
13696 wifi_setApSecurityMFPConfig(ap_index, mfp);
13697
13698 memset(&params, 0, sizeof(params));
13699 params.name = "transition_disable";
13700 if (security->wpa3_transition_disable == TRUE)
13701 params.value = "0x01";
13702 else
13703 params.value = "0x00";
13704 wifi_hostapdWrite(config_file, &params, 1);
13705
13706 memset(&params, 0, sizeof(params));
13707 params.name = "wpa_group_rekey";
13708 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13709 params.value = buf;
13710 wifi_hostapdWrite(config_file, &params, 1);
13711
13712 memset(&params, 0, sizeof(params));
13713 params.name = "wpa_strict_rekey";
13714 params.value = security->strict_rekey?"1":"0";
13715 wifi_hostapdWrite(config_file, &params, 1);
13716
13717 memset(&params, 0, sizeof(params));
13718 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013719 if (security->eapol_key_retries == 0)
13720 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013721 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13722 params.value = buf;
13723 wifi_hostapdWrite(config_file, &params, 1);
13724
13725 memset(&params, 0, sizeof(params));
13726 params.name = "disable_pmksa_caching";
13727 params.value = security->disable_pmksa_caching?"1":"0";
13728 wifi_hostapdWrite(config_file, &params, 1);
13729
developer23e71282023-01-18 10:25:19 +080013730 if (multiple_set == FALSE) {
13731 wifi_setApEnable(ap_index, FALSE);
13732 wifi_setApEnable(ap_index, TRUE);
13733 }
developer587c1b62022-09-27 15:58:59 +080013734
13735 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13736
developer06a01d92022-09-07 16:32:39 +080013737 return RETURN_OK;
13738}
13739
13740INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13741{
developer9df4e652022-10-11 11:27:38 +080013742 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013743 char config_file[128] = {0};
13744 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013745 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013746
13747 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13748 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13749 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13750 security->mode = wifi_security_mode_none;
13751 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013752 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013753 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013754 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013755 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013756 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013757 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013758 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013759 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013760 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013761 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013762 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013763 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013764 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013765 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013766 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013767 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013768 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013769 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013770 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013771 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013772 }
13773
13774 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13775 if (security->mode == wifi_security_mode_none)
13776 security->encr = wifi_encryption_none;
13777 else {
13778 if (strcmp(buf, "TKIP") == 0)
13779 security->encr = wifi_encryption_tkip;
13780 else if (strcmp(buf, "CCMP") == 0)
13781 security->encr = wifi_encryption_aes;
13782 else
13783 security->encr = wifi_encryption_aes_tkip;
13784 }
13785
developer9df4e652022-10-11 11:27:38 +080013786 if (security->mode != wifi_encryption_none) {
13787 memset(buf, 0, sizeof(buf));
13788 // wpa3 can use one or both configs as password, so we check sae_password first.
13789 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013790 if (strlen(buf) != 0) {
13791 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13792 security->u.key.type = wifi_security_key_type_sae;
13793 set_sae = TRUE;
13794 strncpy(security->u.key.key, buf, sizeof(buf));
13795 }
13796 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13797 if (strlen(buf) != 0){
13798 if (set_sae == TRUE)
13799 security->u.key.type = wifi_security_key_type_psk_sae;
13800 else if (strlen(buf) == 64)
13801 security->u.key.type = wifi_security_key_type_psk;
13802 else
13803 security->u.key.type = wifi_security_key_type_pass;
13804 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013805 }
developer9df4e652022-10-11 11:27:38 +080013806 security->u.key.key[255] = '\0';
13807 }
13808
developer587c1b62022-09-27 15:58:59 +080013809 memset(buf, 0, sizeof(buf));
13810 wifi_getApSecurityMFPConfig(ap_index, buf);
13811 if (strcmp(buf, "Disabled") == 0)
13812 security->mfp = wifi_mfp_cfg_disabled;
13813 else if (strcmp(buf, "Optional") == 0)
13814 security->mfp = wifi_mfp_cfg_optional;
13815 else if (strcmp(buf, "Required") == 0)
13816 security->mfp = wifi_mfp_cfg_required;
13817
13818 memset(buf, 0, sizeof(buf));
13819 security->wpa3_transition_disable = FALSE;
13820 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13821 disable = strtol(buf, NULL, 16);
13822 if (disable != 0)
13823 security->wpa3_transition_disable = TRUE;
13824
13825 memset(buf, 0, sizeof(buf));
13826 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13827 if (strlen(buf) == 0)
13828 security->rekey_interval = 86400;
13829 else
13830 security->rekey_interval = strtol(buf, NULL, 10);
13831
13832 memset(buf, 0, sizeof(buf));
13833 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13834 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013835 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013836 else
13837 security->strict_rekey = strtol(buf, NULL, 10);
13838
13839 memset(buf, 0, sizeof(buf));
13840 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13841 if (strlen(buf) == 0)
13842 security->eapol_key_retries = 4;
13843 else
13844 security->eapol_key_retries = strtol(buf, NULL, 10);
13845
13846 memset(buf, 0, sizeof(buf));
13847 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13848 if (strlen(buf) == 0)
13849 security->disable_pmksa_caching = FALSE;
13850 else
13851 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13852
13853 /* TODO
13854 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13855 */
13856 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13857 security->eap_identity_req_timeout = 0;
13858 security->eap_identity_req_retries = 0;
13859 security->eap_req_timeout = 0;
13860 security->eap_req_retries = 0;
13861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013862 return RETURN_OK;
13863}
13864
13865#endif /* WIFI_HAL_VERSION_3 */
13866
13867#ifdef WIFI_HAL_VERSION_3_PHASE2
13868INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13869{
developerd946fd62022-12-08 18:03:28 +080013870 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013871 char cmd[128] = {0};
13872 char buf[128] = {0};
13873 char *mac_addr = NULL;
13874 BOOL status = FALSE;
13875 size_t len = 0;
13876
13877 if(ap_index > MAX_APS)
13878 return RETURN_ERR;
13879
13880 *output_numDevices = 0;
13881 wifi_getApEnable(ap_index, &status);
13882 if (status == FALSE)
13883 return RETURN_OK;
13884
developerac6f1142022-12-20 19:26:35 +080013885 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013886 return RETURN_ERR;
13887 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013888 _syscmd(cmd, buf, sizeof(buf));
13889
13890 mac_addr = strtok(buf, "\n");
13891 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13892 *output_numDevices = i + 1;
13893 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13894 addr_ptr = output_deviceMacAddressArray[i];
13895 mac_addr_aton(addr_ptr, mac_addr);
13896 mac_addr = strtok(NULL, "\n");
13897 }
13898
13899 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013900}
13901#else
13902INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13903{
developerd946fd62022-12-08 18:03:28 +080013904 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013905 char cmd[128];
13906 BOOL status = false;
13907
13908 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13909 return RETURN_ERR;
13910
13911 output_buf[0] = '\0';
13912
13913 wifi_getApEnable(ap_index,&status);
13914 if (!status)
13915 return RETURN_OK;
13916
developerac6f1142022-12-20 19:26:35 +080013917 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013918 return RETURN_ERR;
13919 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013920 _syscmd(cmd, output_buf, output_buf_size);
13921
13922 return RETURN_OK;
13923}
13924#endif
developer2f513ab2022-09-13 14:26:06 +080013925
13926INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13927{
13928 char output[16]={'\0'};
13929 char config_file[MAX_BUF_SIZE] = {0};
13930
13931 if (!enable)
13932 return RETURN_ERR;
13933
13934 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13935 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13936
13937 if (strlen(output) == 0)
13938 *enable = FALSE;
13939 else if (strncmp(output, "1", 1) == 0)
13940 *enable = TRUE;
13941 else
13942 *enable = FALSE;
13943
13944 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13945 return RETURN_OK;
13946}
developer2d9c30f2022-09-13 15:06:14 +080013947
13948INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13949{
developer804c64f2022-10-19 13:54:40 +080013950 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013951 return RETURN_ERR;
13952 *output_enable=TRUE;
13953 return RETURN_OK;
13954}
developerfd7d2892022-09-13 16:44:53 +080013955
13956INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13957{
13958 char cmd[128] = {0};
13959 char buf[128] = {0};
13960 char line[128] = {0};
13961 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013962 FILE *f = NULL;
13963 int index = 0;
13964 int exp = 0;
13965 int mantissa = 0;
13966 int duration = 0;
13967 int radio_index = 0;
13968 int max_radio_num = 0;
13969 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013970 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013971 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13972
13973 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013974
developerfd7d2892022-09-13 16:44:53 +080013975 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013976
13977 phyId = radio_index_to_phy(radio_index);
13978 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013979 _syscmd(cmd, buf, sizeof(buf));
13980 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13981 if (*numSessionReturned > maxNumberSessions)
13982 *numSessionReturned = maxNumberSessions;
13983 else if (*numSessionReturned < 1) {
13984 *numSessionReturned = 0;
13985 return RETURN_OK;
13986 }
13987
developer033b37b2022-10-18 11:27:46 +080013988 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 +080013989 if ((f = popen(cmd, "r")) == NULL) {
13990 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13991 return RETURN_ERR;
13992 }
13993
13994 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013995 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013996 char *tmp = NULL;
13997 strcpy(buf, line);
13998 tmp = strtok(buf, " ");
13999 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
14000 tmp = strtok(NULL, " ");
14001 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
14002 tmp = strtok(NULL, " ");
14003 if (strstr(tmp, "t")) {
14004 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
14005 }
14006 if (strstr(tmp, "a")) {
14007 twtSessions[index].twtParameters.operation.announced = TRUE;
14008 }
14009 tmp = strtok(NULL, " ");
14010 exp = strtol(tmp, NULL, 10);
14011 tmp = strtok(NULL, " ");
14012 mantissa = strtol(tmp, NULL, 10);
14013 tmp = strtok(NULL, " ");
14014 duration = strtol(tmp, NULL, 10);
14015
14016 // only implicit supported
14017 twtSessions[index].twtParameters.operation.implicit = TRUE;
14018 // only individual agreement supported
14019 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
14020
14021 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
14022 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080014023 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080014024 // Overflow handling
14025 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
14026 } else {
14027 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
14028 }
14029 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
14030 index++;
14031 }
14032
14033 pclose(f);
14034 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14035 return RETURN_OK;
14036}