blob: 553530418ea1b123d2785eb82c23be773e557778 [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
developer7930d352022-12-21 17:55:42 +080066#define MAX_BUF_SIZE 256
67#define MAX_CMD_SIZE 256
68#define IF_NAME_SIZE 16
developer06a01d92022-09-07 16:32:39 +080069#define CONFIG_PREFIX "/nvram/hostapd"
developer431128d2022-12-16 15:30:41 +080070#define ACL_PREFIX "/nvram/hostapd-acl"
71#define DENY_PREFIX "/nvram/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080072//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
73#define SOCK_PREFIX "/var/run/hostapd/wifi"
developer431128d2022-12-16 15:30:41 +080074#define VAP_STATUS_FILE "/nvram/vap-status"
developera3c68b92022-09-13 15:27:29 +080075#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080076#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080077#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080078#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080079#define VLAN_FILE "/nvram/hostapd.vlan"
developer431128d2022-12-16 15:30:41 +080080#define PSK_FILE "/nvram/hostapd"
developerf49437e2022-09-29 19:58:21 +080081#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080082#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080083
developer81bf2ed2022-09-13 15:31:14 +080084#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080085
86/*
87 MAX_APS - Number of all AP available in system
88 2x Home AP
89 2x Backhaul AP
90 2x Guest AP
91 2x Secure Onboard AP
92 2x Service AP
93
94*/
developer06a01d92022-09-07 16:32:39 +080095
developer033b37b2022-10-18 11:27:46 +080096
developera77d84b2023-02-22 16:10:50 +080097#define MAX_APS ((MAX_NUM_RADIOS)*(MAX_NUM_VAP_PER_RADIO))
developer06a01d92022-09-07 16:32:39 +080098#ifndef AP_PREFIX
99#define AP_PREFIX "wifi"
100#endif
101
102#ifndef RADIO_PREFIX
103#define RADIO_PREFIX "wlan"
104#endif
105
developer89df4502023-02-16 20:45:02 +0800106#define MAX_ASSOCIATED_STA_NUM 2007 // hostapd default
developer06a01d92022-09-07 16:32:39 +0800107
108//Uncomment to enable debug logs
109//#define WIFI_DEBUG
110
111#ifdef WIFI_DEBUG
112#define wifi_dbg_printf printf
113#define WIFI_ENTRY_EXIT_DEBUG printf
114#else
115#define wifi_dbg_printf(format, args...) printf("")
116#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
117#endif
118
119#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
120#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
121#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
122#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
123#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
124#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
125#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
126#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
127#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
128#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
129
developer4fb0b922022-09-30 14:29:09 +0800130#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800131
132#define BW_FNAME "/nvram/bw_file.txt"
133
134#define PS_MAX_TID 16
135
136static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
137 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
138 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
139 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
140 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
141 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
142 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
143 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
144 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
153};
154
155typedef unsigned long long u64;
156
157/* Enum to define WiFi Bands */
158typedef enum
159{
160 band_invalid = -1,
161 band_2_4 = 0,
162 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800163 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800164} wifi_band;
165
developerdb744382022-09-13 15:34:54 +0800166typedef enum {
167 WIFI_MODE_A = 0x01,
168 WIFI_MODE_B = 0x02,
169 WIFI_MODE_G = 0x04,
170 WIFI_MODE_N = 0x08,
171 WIFI_MODE_AC = 0x10,
172 WIFI_MODE_AX = 0x20,
developer7c4cd202023-03-01 10:56:29 +0800173 WIFI_MODE_BE = 0x40,
developerdb744382022-09-13 15:34:54 +0800174} wifi_ieee80211_Mode;
175
developer06a01d92022-09-07 16:32:39 +0800176#ifdef WIFI_HAL_VERSION_3
177
178// Return number of elements in array
179#ifndef ARRAY_SIZE
180#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
181#endif /* ARRAY_SIZE */
182
183#ifndef ARRAY_AND_SIZE
184#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
185#endif /* ARRAY_AND_SIZE */
186
187#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
188
189typedef struct {
190 int32_t value;
191 int32_t param;
192 intptr_t key;
193 intptr_t data;
194} wifi_secur_list;
195
developerfa41b1f2023-01-06 10:25:51 +0800196static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
197static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
developer72ec5572023-01-05 16:27:13 +0800198static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer06a01d92022-09-07 16:32:39 +0800199wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
200wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
201char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800202static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800203
204static wifi_secur_list map_security[] =
205{
206 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
207 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
208 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800214 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800216 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800217 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800218};
219
220wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
221{
222 wifi_secur_list *item;
223 int i;
224
225 for (item = list,i = 0;i < list_sz; item++, i++) {
226 if ((int)(item->key) == key) {
227 return item;
228 }
229 }
230
231 return NULL;
232}
233
234char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
235{
236 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
237
238 if (!item) {
239 return "";
240 }
241
242 return (char *)(item->data);
243}
244
245wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
246{
247 wifi_secur_list *item;
248 int i;
249
250 for (item = list,i = 0;i < list_sz; item++, i++) {
251 if (strcmp((char *)(item->data), str) == 0) {
252 return item;
253 }
254 }
255
256 return NULL;
257}
258#endif /* WIFI_HAL_VERSION_3 */
259
260#ifdef HAL_NETLINK_IMPL
261typedef struct {
262 int id;
263 struct nl_sock* socket;
264 struct nl_cb* cb;
265} Netlink;
266
267static int mac_addr_aton(unsigned char *mac_addr, char *arg)
268{
269 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800270 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 +0800271 mac_addr[0] = mac_addr_int[0];
272 mac_addr[1] = mac_addr_int[1];
273 mac_addr[2] = mac_addr_int[2];
274 mac_addr[3] = mac_addr_int[3];
275 mac_addr[4] = mac_addr_int[4];
276 mac_addr[5] = mac_addr_int[5];
277 return 0;
278}
279
280static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
281{
282 unsigned int mac_addr_int[6]={};
283 mac_addr_int[0] = arg[0];
284 mac_addr_int[1] = arg[1];
285 mac_addr_int[2] = arg[2];
286 mac_addr_int[3] = arg[3];
287 mac_addr_int[4] = arg[4];
288 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800289 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 +0800290 return;
291}
292
293static int ieee80211_frequency_to_channel(int freq)
294{
developerf5745ee2022-10-05 16:09:53 +0800295 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800296 if (freq == 2484)
297 return 14;
developerf5745ee2022-10-05 16:09:53 +0800298 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
299 else if (freq == 5935)
300 return 2;
developer06a01d92022-09-07 16:32:39 +0800301 else if (freq < 2484)
302 return (freq - 2407) / 5;
303 else if (freq >= 4910 && freq <= 4980)
304 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800305 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800306 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800307 else if (freq <= 45000) /* DMG band lower limit */
308 /* see 802.11ax D6.1 27.3.23.2 */
309 return (freq - 5950) / 5;
310 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800311 return (freq - 56160) / 2160;
312 else
313 return 0;
314}
315
316static int initSock80211(Netlink* nl) {
317 nl->socket = nl_socket_alloc();
318 if (!nl->socket) {
319 fprintf(stderr, "Failing to allocate the sock\n");
320 return -ENOMEM;
321 }
322
323 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
324
325 if (genl_connect(nl->socket)) {
326 fprintf(stderr, "Failed to connect\n");
327 nl_close(nl->socket);
328 nl_socket_free(nl->socket);
329 return -ENOLINK;
330 }
331
332 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
333 if (nl->id< 0) {
334 fprintf(stderr, "interface not found.\n");
335 nl_close(nl->socket);
336 nl_socket_free(nl->socket);
337 return -ENOENT;
338 }
339
340 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
341 if ((!nl->cb)) {
342 fprintf(stderr, "Failed to allocate netlink callback.\n");
343 nl_close(nl->socket);
344 nl_socket_free(nl->socket);
345 return ENOMEM;
346 }
347
348 return nl->id;
349}
350
351static int nlfree(Netlink *nl)
352{
353 nl_cb_put(nl->cb);
354 nl_close(nl->socket);
355 nl_socket_free(nl->socket);
356 return 0;
357}
358
359static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
360 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
361 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
362 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
363};
364
365static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
366};
367
368static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
369};
370
371typedef struct _wifi_channelStats_loc {
372 INT array_size;
373 INT ch_number;
374 BOOL ch_in_pool;
375 INT ch_noise;
376 BOOL ch_radar_noise;
377 INT ch_max_80211_rssi;
378 INT ch_non_80211_noise;
379 INT ch_utilization;
380 ULLONG ch_utilization_total;
381 ULLONG ch_utilization_busy;
382 ULLONG ch_utilization_busy_tx;
383 ULLONG ch_utilization_busy_rx;
384 ULLONG ch_utilization_busy_self;
385 ULLONG ch_utilization_busy_ext;
386} wifi_channelStats_t_loc;
387
388typedef struct wifi_device_info {
389 INT wifi_devIndex;
390 UCHAR wifi_devMacAddress[6];
391 CHAR wifi_devIPAddress[64];
392 BOOL wifi_devAssociatedDeviceAuthentiationState;
393 INT wifi_devSignalStrength;
394 INT wifi_devTxRate;
395 INT wifi_devRxRate;
396} wifi_device_info_t;
397
398#endif
399
400//For 5g Alias Interfaces
401static BOOL priv_flag = TRUE;
402static BOOL pub_flag = TRUE;
403static BOOL Radio_flag = TRUE;
404//wifi_setApBeaconRate(1, beaconRate);
405
developer1e5aa162022-09-13 16:06:24 +0800406BOOL multiple_set = FALSE;
407
developer06a01d92022-09-07 16:32:39 +0800408struct params
409{
410 char * name;
411 char * value;
412};
413
414static int _syscmd(char *cmd, char *retBuf, int retBufSize)
415{
416 FILE *f;
417 char *ptr = retBuf;
418 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
419
420 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
421 if((f = popen(cmd, "r")) == NULL) {
422 fprintf(stderr,"\npopen %s error\n", cmd);
423 return RETURN_ERR;
424 }
425
426 while(!feof(f))
427 {
428 *ptr = 0;
429 if(bufSize>=128) {
430 bufbytes=128;
431 } else {
432 bufbytes=bufSize-1;
433 }
434
435 fgets(ptr,bufbytes,f);
436 readbytes=strlen(ptr);
437
438 if(!readbytes)
439 break;
440
441 bufSize-=readbytes;
442 ptr += readbytes;
443 }
444 cmd_ret = pclose(f);
445 retBuf[retBufSize-1]=0;
446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
447
448 return cmd_ret >> 8;
449}
450
developer033b37b2022-10-18 11:27:46 +0800451INT radio_index_to_phy(int radioIndex)
452{
453 char cmd[128] = {0};
454 char buf[64] = {0};
455 int phyIndex = 0;
456 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
457 _syscmd(cmd, buf, sizeof(buf));
458
459 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800460 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800461 return RETURN_ERR;
462 }
463 sscanf(buf, "phy%d", &phyIndex);
464
465 return phyIndex;
466}
developer026ac9e2022-11-07 13:46:24 +0800467
developer431128d2022-12-16 15:30:41 +0800468INT wifi_getMaxRadioNumber(INT *max_radio_num)
469{
470 char cmd[64] = {0};
471 char buf[4] = {0};
472
473 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
474
475 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
476 _syscmd(cmd, buf, sizeof(buf));
477 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
478
479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
480
481 return RETURN_OK;
482}
483
developer59ff6de2023-02-08 17:58:14 +0800484static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
485{
486 char cmd[MAX_CMD_SIZE]={'\0'};
487 char buf[MAX_BUF_SIZE]={'\0'};
488 int ret = 0;
489
490 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
491 ret = _syscmd(cmd, buf, sizeof(buf));
492 if ((ret != 0) && (strlen(buf) == 0))
493 return -1;
494 snprintf(output, output_size, "%s", buf);
495
496 return 0;
497}
498
499static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
500{
501 char cmd[MAX_CMD_SIZE]={'\0'};
502 char buf[MAX_BUF_SIZE]={'\0'};
503
504 for(int i=0;i<item_count;i++)
505 {
506 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
507 if (strlen(buf) == 0) //Insert
508 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
509 else //Update
510 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
511
512 if(_syscmd(cmd, buf, sizeof(buf)))
513 return -1;
514 }
515
516 return 0;
517}
518
developer431128d2022-12-16 15:30:41 +0800519wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800520{
521 char cmd[128] = {0};
522 char buf[64] = {0};
developer59ff6de2023-02-08 17:58:14 +0800523 char config_file[128] = {0};
developer026ac9e2022-11-07 13:46:24 +0800524 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800525 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800526 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800527 int radioIndex = 0;
528 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800529 wifi_band band = band_invalid;
530
531 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800532
developer431128d2022-12-16 15:30:41 +0800533 wifi_getMaxRadioNumber(&max_radio_num);
534 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800535 phyIndex = radio_index_to_phy(radioIndex);
developer59ff6de2023-02-08 17:58:14 +0800536 snprintf(cmd, sizeof(cmd), "cat /sys/class/ieee80211/phy%d/device/device 2> /dev/null", phyIndex);
537 _syscmd(cmd, buf, sizeof(buf));
538 if (strncmp(buf, "0x7915", 6) == 0) { // harrier have two bands, consider as a special case.
539 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
540 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
541 if (strncmp(buf, "a", 1) == 0)
542 return band_5;
543 else
544 return band_2_4;
545 }
developer5884e982022-10-06 10:52:50 +0800546 while(i < 10){
developer59ff6de2023-02-08 17:58:14 +0800547 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tr -d ':\\n' | awk '{print $2}'", phyIndex);
developer5884e982022-10-06 10:52:50 +0800548 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800549 nl80211_band = strtol(buf, NULL, 10);
550 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800551 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800552 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800553 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800554 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800555 band = band_6;
556
557 if(band != band_invalid)
558 break;
559
560 i++;
561 sleep(1);
562 }
developerc707e972022-09-13 15:38:02 +0800563
564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
565 return band;
566}
567
developerd946fd62022-12-08 18:03:28 +0800568//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800569static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800570{
571 char config_file[128] = {0};
572
573 if (interface_name == NULL)
574 return RETURN_ERR;
575
576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
577
578 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
579 wifi_hostapdRead(config_file, "interface", interface_name, 16);
580 if (strlen(interface_name) == 0)
581 return RETURN_ERR;
582
583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
584 return RETURN_OK;
585}
586
developerac6f1142022-12-20 19:26:35 +0800587// wifi agent will call this function, do not change the parameter
588void GetInterfaceName(char *interface_name, char *conf_file)
589{
590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
591 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
593}
594
developer06a01d92022-09-07 16:32:39 +0800595static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
596{
developerd946fd62022-12-08 18:03:28 +0800597 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800598 if (multiple_set == TRUE)
599 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800600 char cmd[MAX_CMD_SIZE]="", output[32]="";
601 FILE *fp;
602 int i;
603 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800604 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800605 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800606 for(i=0; i<item_count; i++, list++)
607 {
developerd946fd62022-12-08 18:03:28 +0800608 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800609 if((fp = popen(cmd, "r"))==NULL)
610 {
611 perror("popen failed");
612 return -1;
613 }
614 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
615 {
616 pclose(fp);
617 perror("fgets failed");
618 return -1;
619 }
620 pclose(fp);
621 }
622 return 0;
623}
624
625static int wifi_reloadAp(int apIndex)
626{
developerd946fd62022-12-08 18:03:28 +0800627 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800628 if (multiple_set == TRUE)
629 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800630 char cmd[MAX_CMD_SIZE]="";
631 char buf[MAX_BUF_SIZE]="";
632
developerac6f1142022-12-20 19:26:35 +0800633 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800634 return RETURN_ERR;
635 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800636 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
637 return RETURN_ERR;
638
developerd946fd62022-12-08 18:03:28 +0800639 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800640 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
641 return RETURN_ERR;
642
developerd946fd62022-12-08 18:03:28 +0800643 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800644 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
645 return RETURN_ERR;
646
647 return RETURN_OK;
648}
649
developer06a01d92022-09-07 16:32:39 +0800650INT File_Reading(CHAR *file, char *Value)
651{
652 FILE *fp = NULL;
653 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
654 int count = 0;
655
656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
657 fp = popen(file,"r");
658 if(fp == NULL)
659 return RETURN_ERR;
660
661 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
662 {
663 for(count=0;buf[count]!='\n';count++)
664 copy_buf[count]=buf[count];
665 copy_buf[count]='\0';
666 }
667 strcpy(Value,copy_buf);
668 pclose(fp);
669 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
670
671 return RETURN_OK;
672}
673
674void wifi_RestartHostapd_2G()
675{
676 int Public2GApIndex = 4;
677
678 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
679 wifi_setApEnable(Public2GApIndex, FALSE);
680 wifi_setApEnable(Public2GApIndex, TRUE);
681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
682}
683
684void wifi_RestartHostapd_5G()
685{
686 int Public5GApIndex = 5;
687
688 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
689 wifi_setApEnable(Public5GApIndex, FALSE);
690 wifi_setApEnable(Public5GApIndex, TRUE);
691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
692}
693
694void wifi_RestartPrivateWifi_2G()
695{
696 int PrivateApIndex = 0;
697
698 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
699 wifi_setApEnable(PrivateApIndex, FALSE);
700 wifi_setApEnable(PrivateApIndex, TRUE);
701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
702}
703
704void wifi_RestartPrivateWifi_5G()
705{
706 int Private5GApIndex = 1;
707
708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
709 wifi_setApEnable(Private5GApIndex, FALSE);
710 wifi_setApEnable(Private5GApIndex, TRUE);
711 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
712}
713
714static int writeBandWidth(int radioIndex,char *bw_value)
715{
716 char buf[MAX_BUF_SIZE];
717 char cmd[MAX_CMD_SIZE];
718
719 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
720 if(_syscmd(cmd, buf, sizeof(buf)))
721 {
722 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
723 _syscmd(cmd, buf, sizeof(buf));
724 return RETURN_OK;
725 }
726
727 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
728 _syscmd(cmd,buf,sizeof(buf));
729 return RETURN_OK;
730}
731
732static int readBandWidth(int radioIndex,char *bw_value)
733{
developer30423732022-12-01 16:17:49 +0800734 char buf[MAX_BUF_SIZE] = {0};
735 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800736 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
737 _syscmd(cmd,buf,sizeof(buf));
738 if(NULL!=strstr(buf,"20MHz"))
developer06a01d92022-09-07 16:32:39 +0800739 strcpy(bw_value,"20MHz");
developer06a01d92022-09-07 16:32:39 +0800740 else if(NULL!=strstr(buf,"40MHz"))
developer06a01d92022-09-07 16:32:39 +0800741 strcpy(bw_value,"40MHz");
developer06a01d92022-09-07 16:32:39 +0800742 else if(NULL!=strstr(buf,"80MHz"))
developer06a01d92022-09-07 16:32:39 +0800743 strcpy(bw_value,"80MHz");
developer57fa24a2023-03-15 17:25:07 +0800744 else if(NULL!=strstr(buf,"160MHz"))
745 strcpy(bw_value,"160MHz");
746 else if(NULL!=strstr(buf,"320MHz"))
747 strcpy(bw_value,"320MHz");
developer06a01d92022-09-07 16:32:39 +0800748 else
developer06a01d92022-09-07 16:32:39 +0800749 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800750 return RETURN_OK;
751}
752
developer264159b2022-11-02 09:41:35 +0800753// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800754INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
755{
developer5f222492022-09-13 15:21:52 +0800756 struct params params={'\0'};
757 char config_file[MAX_BUF_SIZE] = {0};
758 char buf[MAX_BUF_SIZE] = {'\0'};
759
760 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800761 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800762 if (strlen (beaconRate) >= 5) {
763 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
764 buf[strlen(beaconRate) - 4] = '\0';
765 } else if (strlen(beaconRate) > 0)
766 strcpy(buf, beaconRate);
767 else
768 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800769
770 params.name = "beacon_rate";
771 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
772 if (strncmp(buf, "5.5", 3) == 0) {
773 snprintf(buf, sizeof(buf), "55");
774 params.value = buf;
775 } else {
776 strcat(buf, "0");
777 params.value = buf;
778 }
779
780 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
781 wifi_hostapdWrite(config_file, &params, 1);
782 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
784
785 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800786}
787
788INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
789{
developer1d57d002022-10-12 18:03:15 +0800790 char config_file[128] = {'\0'};
791 char temp_output[128] = {'\0'};
792 char buf[128] = {'\0'};
793 char cmd[128] = {'\0'};
794 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800795 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800796
797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
798 if (NULL == beaconRate)
799 return RETURN_ERR;
800
801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
802 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800803 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800804 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
805 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800806 if (strncmp(buf, "55", 2) == 0)
807 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
808 else {
809 rate = strtol(buf, NULL, 10)/10;
810 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
811 }
developer5f222492022-09-13 15:21:52 +0800812 } else {
developer1d57d002022-10-12 18:03:15 +0800813 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800814 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 +0800815 _syscmd(cmd, buf, sizeof(buf));
816 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800817 }
818 strncpy(beaconRate, temp_output, sizeof(temp_output));
819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
820
821 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800822}
823
824INT wifi_setLED(INT radioIndex, BOOL enable)
825{
826 return 0;
827}
828INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
829{
830 return RETURN_OK;
831}
832/**********************************************************************************
833 *
834 * Wifi Subsystem level function prototypes
835 *
836**********************************************************************************/
837//---------------------------------------------------------------------------------------------------
838//Wifi system api
839//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
840INT wifi_getHalVersion(CHAR *output_string) //RDKB
841{
842 if(!output_string)
843 return RETURN_ERR;
844 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
845
846 return RETURN_OK;
847}
848
849
850/* wifi_factoryReset() function */
851/**
852* @description Clears internal variables to implement a factory reset of the Wi-Fi
853* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
854*
855* @param None
856*
857* @return The status of the operation.
858* @retval RETURN_OK if successful.
859* @retval RETURN_ERR if any error is detected
860*
861* @execution Synchronous
862* @sideeffect None
863*
864* @note This function must not suspend and must not invoke any blocking system
865* calls. It should probably just send a message to a driver event handler task.
866*
867*/
868INT wifi_factoryReset()
869{
870 char cmd[128];
871
872 /*delete running hostapd conf files*/
developer72ec5572023-01-05 16:27:13 +0800873 wifi_dbg_printf("\n[%s]: deleting hostapd conf file",__func__);
874 sprintf(cmd, "rm -rf /nvram/hostapd*");
developer06a01d92022-09-07 16:32:39 +0800875 system(cmd);
876 system("systemctl restart hostapd.service");
877
878 return RETURN_OK;
879}
880
881/* wifi_factoryResetRadios() function */
882/**
883* @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.
884*
885* @param None
886* @return The status of the operation
887* @retval RETURN_OK if successful
888* @retval RETURN_ERR if any error is detected
889*
890* @execution Synchronous
891*
892* @sideeffect None
893*
894* @note This function must not suspend and must not invoke any blocking system
895* calls. It should probably just send a message to a driver event handler task.
896*
897*/
898INT wifi_factoryResetRadios()
899{
developer72ec5572023-01-05 16:27:13 +0800900 int max_radio_num = 0;
901 wifi_getMaxRadioNumber(&max_radio_num);
902 for (int radioIndex = 0; radioIndex < max_radio_num; radioIndex++)
903 wifi_factoryResetRadio(radioIndex);
developer06a01d92022-09-07 16:32:39 +0800904
developer72ec5572023-01-05 16:27:13 +0800905 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800906}
907
908
909/* wifi_factoryResetRadio() function */
910/**
911* @description Restore selected radio parameters without touching access point parameters
912*
913* @param radioIndex - Index of Wi-Fi Radio channel
914*
915* @return The status of the operation.
916* @retval RETURN_OK if successful.
917* @retval RETURN_ERR if any error is detected
918*
919* @execution Synchronous.
920* @sideeffect None.
921*
922* @note This function must not suspend and must not invoke any blocking system
923* calls. It should probably just send a message to a driver event handler task.
924*
925*/
926INT wifi_factoryResetRadio(int radioIndex) //RDKB
927{
developer72ec5572023-01-05 16:27:13 +0800928 char cmd[128] = {0};
929 char buf[128] = {0};
930 int max_radio_num = 0;
931
932 wifi_getMaxRadioNumber(&max_radio_num);
933 if (radioIndex < 0 || radioIndex > max_radio_num)
934 return RETURN_ERR;
935
936 snprintf(cmd, sizeof(cmd), "systemctl stop hostapd.service");
937 _syscmd(cmd, buf, sizeof(buf));
developer5ff7f5f2022-09-13 15:12:16 +0800938
developer06a01d92022-09-07 16:32:39 +0800939 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72ec5572023-01-05 16:27:13 +0800940 snprintf(cmd, sizeof(cmd), "rm /nvram/hostapd%d* %s%d.txt", radioIndex, GUARD_INTERVAL_FILE, radioIndex);
941 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800942
developer72ec5572023-01-05 16:27:13 +0800943 snprintf(cmd, sizeof(cmd), "systemctl start hostapd.service");
944 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800945 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
946 return RETURN_OK;
947}
948
949/* wifi_initRadio() function */
950/**
951* Description: This function call initializes the specified radio.
952* Implementation specifics may dictate the functionality since
953* different hardware implementations may have different initilization requirements.
954* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
955*
956* @return The status of the operation.
957* @retval RETURN_OK if successful.
958* @retval RETURN_ERR if any error is detected
959*
960* @execution Synchronous.
961* @sideeffect None.
962*
963* @note This function must not suspend and must not invoke any blocking system
964* calls. It should probably just send a message to a driver event handler task.
965*
966*/
967INT wifi_initRadio(INT radioIndex)
968{
969 //TODO: Initializes the wifi subsystem (for specified radio)
970 return RETURN_OK;
971}
972void macfilter_init()
973{
974 char count[4]={'\0'};
975 char buf[253]={'\0'};
976 char tmp[19]={'\0'};
977 int dev_count,block,mac_entry=0;
978 char res[4]={'\0'};
979 char acl_file_path[64] = {'\0'};
980 FILE *fp = NULL;
981 int index=0;
982 char iface[10]={'\0'};
983 char config_file[MAX_BUF_SIZE] = {0};
984
985
986 sprintf(acl_file_path,"/tmp/mac_filter.sh");
987
988 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800989 if (fp == NULL) {
990 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
991 return RETURN_ERR;
992 }
developer06a01d92022-09-07 16:32:39 +0800993 sprintf(buf,"#!/bin/sh \n");
994 fprintf(fp,"%s\n",buf);
995
996 system("chmod 0777 /tmp/mac_filter.sh");
997
998 for(index=0;index<=1;index++)
999 {
1000 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1001 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1002 sprintf(buf,"syscfg get %dcountfilter",index);
1003 _syscmd(buf,count,sizeof(count));
1004 mac_entry=atoi(count);
1005
1006 sprintf(buf,"syscfg get %dblockall",index);
1007 _syscmd(buf,res,sizeof(res));
1008 block = atoi(res);
1009
1010 //Allow only those macs mentioned in ACL
1011 if(block==1)
1012 {
1013 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1014 fprintf(fp,"%s\n",buf);
1015 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1016 {
1017 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1018 _syscmd(buf,tmp,sizeof(tmp));
1019 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1020 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1021 fprintf(fp,"%s\n",buf);
1022 }
1023 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1024 fprintf(fp,"%s\n",buf);
1025 }
1026
1027 //Block all the macs mentioned in ACL
1028 else if(block==2)
1029 {
1030 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1031 fprintf(fp,"%s\n",buf);
1032
1033 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1034 {
1035 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1036 _syscmd(buf,tmp,sizeof(tmp));
1037 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1038 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1039 fprintf(fp,"%s\n",buf);
1040 }
1041 }
1042 }
1043 fclose(fp);
1044}
1045
1046// Initializes the wifi subsystem (all radios)
1047INT wifi_init() //RDKB
1048{
1049 char interface[MAX_BUF_SIZE]={'\0'};
1050 char bridge_name[MAX_BUF_SIZE]={'\0'};
1051 INT len=0;
1052
1053 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1054 //Not intitializing macfilter for Turris-Omnia Platform for now
1055 //macfilter_init();
1056
1057 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001058 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001059 sleep(2);//sleep to wait for hostapd to start
1060
1061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1062
1063 return RETURN_OK;
1064}
1065
1066/* wifi_reset() function */
1067/**
1068* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1069* Implementation specifics may dictate what is actualy reset since
1070* different hardware implementations may have different requirements.
1071* Parameters : None
1072*
1073* @return The status of the operation.
1074* @retval RETURN_OK if successful.
1075* @retval RETURN_ERR if any error is detected
1076*
1077* @execution Synchronous.
1078* @sideeffect None.
1079*
1080* @note This function must not suspend and must not invoke any blocking system
1081* calls. It should probably just send a message to a driver event handler task.
1082*
1083*/
1084INT wifi_reset()
1085{
1086 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001087 system("systemctl stop hostapd.service");
1088 sleep(2);
1089 system("systemctl start hostapd.service");
1090 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001091 return RETURN_OK;
1092}
1093
1094/* wifi_down() function */
1095/**
1096* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1097* Implementation specifics may dictate some functionality since
1098* different hardware implementations may have different requirements.
1099*
1100* @param None
1101*
1102* @return The status of the operation
1103* @retval RETURN_OK if successful
1104* @retval RETURN_ERR if any error is detected
1105*
1106* @execution Synchronous
1107* @sideeffect None
1108*
1109* @note This function must not suspend and must not invoke any blocking system
1110* calls. It should probably just send a message to a driver event handler task.
1111*
1112*/
1113INT wifi_down()
1114{
1115 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer72ec5572023-01-05 16:27:13 +08001116 int max_num_radios = 0;
1117 wifi_getMaxRadioNumber(&max_num_radios);
1118 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1119 wifi_setRadioEnable(radioIndex, FALSE);
1120
developer06a01d92022-09-07 16:32:39 +08001121 return RETURN_OK;
1122}
1123
1124
1125/* wifi_createInitialConfigFiles() function */
1126/**
1127* @description This function creates wifi configuration files. The format
1128* and content of these files are implementation dependent. This function call is
1129* used to trigger this task if necessary. Some implementations may not need this
1130* function. If an implementation does not need to create config files the function call can
1131* do nothing and return RETURN_OK.
1132*
1133* @param None
1134*
1135* @return The status of the operation
1136* @retval RETURN_OK if successful
1137* @retval RETURN_ERR if any error is detected
1138*
1139* @execution Synchronous
1140* @sideeffect None
1141*
1142* @note This function must not suspend and must not invoke any blocking system
1143* calls. It should probably just send a message to a driver event handler task.
1144*
1145*/
1146INT wifi_createInitialConfigFiles()
1147{
1148 //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)
1149 return RETURN_OK;
1150}
1151
1152// outputs the country code to a max 64 character string
1153INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1154{
developerd946fd62022-12-08 18:03:28 +08001155 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001156 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001157 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001158 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001159
developerac6f1142022-12-20 19:26:35 +08001160 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001161 return RETURN_ERR;
1162 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001163 _syscmd(cmd, buf, sizeof(buf));
1164 if(strlen(buf) > 0)
1165 snprintf(output_string, 64, "%s", buf);
1166 else
1167 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001168
1169 return RETURN_OK;
1170}
1171
1172INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1173{
1174 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001175 char str[MAX_BUF_SIZE]={'\0'};
1176 char cmd[MAX_CMD_SIZE]={'\0'};
1177 struct params params;
1178 char config_file[MAX_BUF_SIZE] = {0};
1179
1180 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1181 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1182 return RETURN_ERR;
1183
developerb86c6f32022-10-07 14:34:58 +08001184 if (strlen(CountryCode) == 0)
1185 strcpy(CountryCode, "US");
1186
developer7543b3b2022-09-13 13:47:17 +08001187 params.name = "country_code";
1188 params.value = CountryCode;
1189 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1190 int ret = wifi_hostapdWrite(config_file, &params, 1);
1191 if (ret) {
1192 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1193 ,__func__, ret);
1194 }
1195
1196 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1197 if (ret) {
1198 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1199 ,__func__, ret);
1200 }
developer7543b3b2022-09-13 13:47:17 +08001201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1202
developer06a01d92022-09-07 16:32:39 +08001203 return RETURN_OK;
1204}
1205
developera748dcf2022-09-13 15:56:48 +08001206INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1207{
developerd946fd62022-12-08 18:03:28 +08001208 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001209 char channel_util_file[64] = {0};
1210 char cmd[128] = {0};
1211 char buf[128] = {0};
1212 char line[128] = {0};
1213 char *param = NULL, *value = NULL;
1214 int read = 0;
1215 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1216 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1217 size_t len = 0;
1218 FILE *f = NULL;
1219
1220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1221
developerac6f1142022-12-20 19:26:35 +08001222 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001223 return RETURN_ERR;
1224 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001225 _syscmd(cmd, buf, sizeof(buf));
1226 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1227
1228 memset(cmd, 0, sizeof(cmd));
1229 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001230 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001231 if ((f = popen(cmd, "r")) == NULL) {
1232 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1233 return RETURN_ERR;
1234 }
1235
1236 read = getline(&line, &len, f);
1237 while (read != -1) {
1238 param = strtok(line, ":\t");
1239 value = strtok(NULL, " ");
1240 if(strstr(param, "frequency") != NULL) {
1241 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1242 }
1243 if(strstr(param, "noise") != NULL) {
1244 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1245 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1246 }
1247 if(strstr(param, "channel active time") != NULL) {
1248 ActiveTime = strtol(value, NULL, 10);
1249 }
1250 if(strstr(param, "channel busy time") != NULL) {
1251 BusyTime = strtol(value, NULL, 10);
1252 }
1253 if(strstr(param, "channel transmit time") != NULL) {
1254 TransmitTime = strtol(value, NULL, 10);
1255 }
1256 read = getline(&line, &len, f);
1257 }
1258 pclose(f);
1259
1260 // The file should store the last active, busy and transmit time
1261 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1262 f = fopen(channel_util_file, "r");
1263 if (f != NULL) {
1264 read = getline(&line, &len, f);
1265 preActiveTime = strtol(line, NULL, 10);
1266 read = getline(&line, &len, f);
1267 preBusyTime = strtol(line, NULL, 10);
1268 read = getline(&line, &len, f);
1269 preTransmitTime = strtol(line, NULL, 10);
1270 fclose(f);
1271 }
1272
1273 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1274 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1275
1276 f = fopen(channel_util_file, "w");
1277 if (f != NULL) {
1278 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1279 fclose(f);
1280 }
1281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1282 return RETURN_OK;
1283}
1284
developer06a01d92022-09-07 16:32:39 +08001285/**********************************************************************************
1286 *
1287 * Wifi radio level function prototypes
1288 *
1289**********************************************************************************/
1290
1291//Get the total number of radios in this wifi subsystem
1292INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1293{
1294 if (NULL == output)
1295 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001296 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001297
1298 return RETURN_OK;
1299}
1300
1301//Get the total number of SSID entries in this wifi subsystem
1302INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1303{
1304 if (NULL == output)
1305 return RETURN_ERR;
1306 *output = MAX_APS;
1307
1308 return RETURN_OK;
1309}
1310
1311//Get the Radio enable config parameter
1312INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1313{
developerd946fd62022-12-08 18:03:28 +08001314 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001315 char buf[128] = {0}, cmd[128] = {0};
developera77d84b2023-02-22 16:10:50 +08001316 int apIndex;
1317 int max_radio_num = 0;
developer06a01d92022-09-07 16:32:39 +08001318
1319 if (NULL == output_bool)
1320 return RETURN_ERR;
1321
1322 *output_bool = FALSE;
developera77d84b2023-02-22 16:10:50 +08001323
1324 wifi_getMaxRadioNumber(&max_radio_num);
1325
1326 if (radioIndex >= max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001327 return RETURN_ERR;
1328
developera77d84b2023-02-22 16:10:50 +08001329 /* loop all interface in radio, if any is enable, reture true, else return false */
1330 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1331 {
developer643b28f2023-04-04 10:26:01 +08001332 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developera77d84b2023-02-22 16:10:50 +08001333 continue;
1334 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1335 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001336
developera77d84b2023-02-22 16:10:50 +08001337 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 ||
1338 strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0) {
1339 /* return true if any interface is eanble */
1340 *output_bool = TRUE;
1341 break;
1342 }
1343 }
developer06a01d92022-09-07 16:32:39 +08001344 return RETURN_OK;
1345}
1346
1347INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1348{
developerd946fd62022-12-08 18:03:28 +08001349 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001350 char cmd[MAX_CMD_SIZE] = {0};
1351 char buf[MAX_CMD_SIZE] = {0};
1352 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001353 int max_radio_num = 0;
1354 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001355
1356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001357
1358 phyId = radio_index_to_phy(radioIndex);
1359
1360 wifi_getMaxRadioNumber(&max_radio_num);
1361
developer06a01d92022-09-07 16:32:39 +08001362 if(enable==FALSE)
1363 {
developera77d84b2023-02-22 16:10:50 +08001364 /* disable from max apindex to min, to avoid fail in mbss case */
1365 for(apIndex=(MAX_APS-max_radio_num+radioIndex); apIndex>=0; apIndex-=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001366 {
developer1e125222022-12-29 09:35:25 +08001367 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001368 continue;
developer1e125222022-12-29 09:35:25 +08001369
developer06a01d92022-09-07 16:32:39 +08001370 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001371 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001372 _syscmd(cmd, buf, sizeof(buf));
1373 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001374 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001375
developer2f18b9f2023-03-17 19:32:57 +08001376 if (!(apIndex/max_radio_num)) {
1377 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1378 _syscmd(cmd, buf, sizeof(buf));
1379 }
developer06a01d92022-09-07 16:32:39 +08001380 }
developer06a01d92022-09-07 16:32:39 +08001381 }
1382 else
1383 {
developer033b37b2022-10-18 11:27:46 +08001384 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001385 {
developer1e125222022-12-29 09:35:25 +08001386 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001387 continue;
developer1e125222022-12-29 09:35:25 +08001388
developer643b28f2023-04-04 10:26:01 +08001389 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001390 _syscmd(cmd, buf, sizeof(buf));
developera77d84b2023-02-22 16:10:50 +08001391 if(*buf == '1') {
developer2f18b9f2023-03-17 19:32:57 +08001392 if (!(apIndex/max_radio_num)) {
1393 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1394 ret = _syscmd(cmd, buf, sizeof(buf));
1395 if ( ret == RETURN_ERR) {
1396 fprintf(stderr, "VAP interface creation failed\n");
1397 continue;
1398 }
developera77d84b2023-02-22 16:10:50 +08001399 }
developer06a01d92022-09-07 16:32:39 +08001400 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001401 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001402 _syscmd(cmd, buf, sizeof(buf));
1403 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001404 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001405 }
1406 }
1407 }
1408
1409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1410 return RETURN_OK;
1411}
1412
1413//Get the Radio enable status
1414INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1415{
1416 if (NULL == output_bool)
1417 return RETURN_ERR;
1418
1419 return wifi_getRadioEnable(radioIndex, output_bool);
1420}
1421
1422//Get the Radio Interface name from platform, eg "wlan0"
1423INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1424{
developer804c64f2022-10-19 13:54:40 +08001425 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001426 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001427 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001428}
1429
1430//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1431//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.
1432INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1433{
developerbcc556a2022-09-22 20:02:45 +08001434 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1435 // For max bit rate, we should always choose the best MCS
1436 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001437 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001438 char *tmp = NULL;
1439 UINT mode_map = 0;
1440 UINT num_subcarrier = 0;
1441 UINT code_bits = 0;
1442 float code_rate = 0; // use max code rate
1443 int NSS = 0;
1444 UINT Symbol_duration = 0;
1445 UINT GI_duration = 0;
1446 wifi_band band = band_invalid;
1447 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1448 BOOL enable = FALSE;
1449 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001450
1451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1452 if (NULL == output_string)
1453 return RETURN_ERR;
1454
developerbcc556a2022-09-22 20:02:45 +08001455 wifi_getRadioEnable(radioIndex, &enable);
1456 if (enable == FALSE) {
1457 snprintf(output_string, 64, "0 Mb/s");
1458 return RETURN_OK;
1459 }
1460
1461 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1462 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1463 return RETURN_ERR;
1464 }
1465
1466 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1467 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1468 return RETURN_ERR;
1469 }
1470
1471 if (gi == wifi_guard_interval_3200)
1472 GI_duration = 32;
1473 else if (gi == wifi_guard_interval_1600)
1474 GI_duration = 16;
1475 else if (gi == wifi_guard_interval_800)
1476 GI_duration = 8;
1477 else // auto, 400
1478 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001479
developerbcc556a2022-09-22 20:02:45 +08001480 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1481 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1482 return RETURN_ERR;
1483 }
1484
1485 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1486 strcpy(channel_bandwidth_str, "160");
1487
1488 if (mode_map & WIFI_MODE_AX) {
1489 if (strstr(channel_bandwidth_str, "160") != NULL)
1490 num_subcarrier = 1960;
1491 else if (strstr(channel_bandwidth_str, "80") != NULL)
1492 num_subcarrier = 980;
1493 else if (strstr(channel_bandwidth_str, "40") != NULL)
1494 num_subcarrier = 468;
1495 else if (strstr(channel_bandwidth_str, "20") != NULL)
1496 num_subcarrier = 234;
1497 code_bits = 10;
1498 code_rate = (float)5/6;
1499 Symbol_duration = 128;
1500 } else if (mode_map & WIFI_MODE_AC) {
1501 if (strstr(channel_bandwidth_str, "160") != NULL)
1502 num_subcarrier = 468;
1503 else if (strstr(channel_bandwidth_str, "80") != NULL)
1504 num_subcarrier = 234;
1505 else if (strstr(channel_bandwidth_str, "40") != NULL)
1506 num_subcarrier = 108;
1507 else if (strstr(channel_bandwidth_str, "20") != NULL)
1508 num_subcarrier = 52;
1509 code_bits = 8;
1510 code_rate = (float)5/6;
1511 Symbol_duration = 32;
1512 } else if (mode_map & WIFI_MODE_N) {
1513 if (strstr(channel_bandwidth_str, "160") != NULL)
1514 num_subcarrier = 468;
1515 else if (strstr(channel_bandwidth_str, "80") != NULL)
1516 num_subcarrier = 234;
1517 else if (strstr(channel_bandwidth_str, "40") != NULL)
1518 num_subcarrier = 108;
1519 else if (strstr(channel_bandwidth_str, "20") != NULL)
1520 num_subcarrier = 52;
1521 code_bits = 6;
1522 code_rate = (float)3/4;
1523 Symbol_duration = 32;
1524 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1525 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1526 snprintf(output_string, 64, "65 Mb/s");
1527 return RETURN_OK;
1528 } else {
1529 snprintf(output_string, 64, "0 Mb/s");
1530 return RETURN_OK;
1531 }
developer06a01d92022-09-07 16:32:39 +08001532
developerbcc556a2022-09-22 20:02:45 +08001533 // Spatial streams
1534 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1535 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1536 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001537 }
developerbcc556a2022-09-22 20:02:45 +08001538
1539 // multiple 10 is to align duration unit (0.1 us)
1540 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1541 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1542
developer06a01d92022-09-07 16:32:39 +08001543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1544
1545 return RETURN_OK;
1546}
1547#if 0
1548INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1549{
1550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1551 char cmd[64];
1552 char buf[1024];
1553 int apIndex;
1554
1555 if (NULL == output_string)
1556 return RETURN_ERR;
1557
1558 apIndex=(radioIndex==0)?0:1;
1559
developerd946fd62022-12-08 18:03:28 +08001560 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001561 _syscmd(cmd,buf, sizeof(buf));
1562
1563 snprintf(output_string, 64, "%s", buf);
1564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1565 return RETURN_OK;
1566}
1567#endif
1568
1569
1570//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1571//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1572INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1573{
developer963da0c2022-09-13 15:58:27 +08001574 wifi_band band = band_invalid;
1575
developer06a01d92022-09-07 16:32:39 +08001576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1577 if (NULL == output_string)
1578 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001579
1580 band = wifi_index_to_band(radioIndex);
1581
1582 memset(output_string, 0, 10);
1583 if (band == band_2_4)
1584 strcpy(output_string, "2.4GHz");
1585 else if (band == band_5)
1586 strcpy(output_string, "5GHz");
1587 else if (band == band_6)
1588 strcpy(output_string, "6GHz");
1589 else
1590 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1592
1593 return RETURN_OK;
1594#if 0
1595 char buf[MAX_BUF_SIZE]={'\0'};
1596 char str[MAX_BUF_SIZE]={'\0'};
1597 char cmd[MAX_CMD_SIZE]={'\0'};
1598 char *ch=NULL;
1599 char *ch2=NULL;
1600
1601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1602 if (NULL == output_string)
1603 return RETURN_ERR;
1604
1605
1606 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1607
1608 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1609 {
1610 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1611 return RETURN_ERR;
1612 }
1613 ch=strchr(buf,'\n');
1614 *ch='\0';
1615 ch=strchr(buf,'=');
1616 if(ch==NULL)
1617 return RETURN_ERR;
1618
1619
1620 ch++;
1621
1622 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1623 strcpy(buf,"0");
1624 if(strlen(ch) == 1)
1625 ch=strcat(buf,ch);
1626
1627
1628 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1629
1630 if(_syscmd(cmd,str,64) == RETURN_ERR)
1631 {
1632 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1633 return RETURN_ERR;
1634 }
1635
1636
1637 ch2=strchr(str,'\n');
1638 //replace \n with \0
1639 *ch2='\0';
1640 ch2=strchr(str,'=');
1641 if(ch2==NULL)
1642 {
1643 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1644 return RETURN_ERR;
1645 }
1646 else
1647 wifi_dbg_printf("%s",ch2+1);
1648
1649
1650 ch2++;
1651
1652
1653 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1654
1655 memset(buf,'\0',sizeof(buf));
1656 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1657 {
1658 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1659 return RETURN_ERR;
1660 }
1661 if (strstr(buf,"2.4") != NULL )
1662 strcpy(output_string,"2.4GHz");
1663 else if(strstr(buf,"5.") != NULL )
1664 strcpy(output_string,"5GHz");
1665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1666
1667 return RETURN_OK;
1668#endif
1669}
1670
1671//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1672//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.
1673INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1674{
developerb7593de2022-10-18 09:51:57 +08001675 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1677 if (NULL == output_string)
1678 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001679 band = wifi_index_to_band(radioIndex);
1680
1681 if (band == band_2_4)
1682 snprintf(output_string, 64, "2.4GHz");
1683 else if (band == band_5)
1684 snprintf(output_string, 64, "5GHz");
1685 else if (band == band_6)
1686 snprintf(output_string, 64, "6GHz");
1687
developer06a01d92022-09-07 16:32:39 +08001688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1689
1690 return RETURN_OK;
1691#if 0
1692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1693 char buf[MAX_BUF_SIZE]={'\0'};
1694 char str[MAX_BUF_SIZE]={'\0'};
1695 char cmd[MAX_CMD_SIZE]={'\0'};
1696 char *ch=NULL;
1697 char *ch2=NULL;
1698 char ch1[5]="0";
1699
1700 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1701
1702 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1703 {
1704 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1705 return RETURN_ERR;
1706 }
1707
1708 ch=strchr(buf,'\n');
1709 *ch='\0';
1710 ch=strchr(buf,'=');
1711 if(ch==NULL)
1712 return RETURN_ERR;
1713 ch++;
1714
1715 if(strlen(ch)==1)
1716 {
1717 strcat(ch1,ch);
1718
1719 }
1720 else
1721 {
1722 strcpy(ch1,ch);
1723 }
1724
1725
1726
1727 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1728 if(_syscmd(cmd,str,64) == RETURN_ERR)
1729 {
1730 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1731 return RETURN_ERR;
1732 }
1733
1734
1735 ch2=strchr(str,'\n');
1736 //replace \n with \0
1737 *ch2='\0';
1738 ch2=strchr(str,'=');
1739 if(ch2==NULL)
1740 {
1741 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1742 return RETURN_ERR;
1743 }
1744 else
1745 wifi_dbg_printf("%s",ch2+1);
1746 ch2++;
1747
1748
1749 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1750 memset(buf,'\0',sizeof(buf));
1751 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1752 {
1753 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1754 return RETURN_ERR;
1755 }
1756
1757
1758 if(strstr(buf,"2.4")!=NULL)
1759 {
1760 strcpy(output_string,"2.4GHz");
1761 }
1762 if(strstr(buf,"5.")!=NULL)
1763 {
1764 strcpy(output_string,"5GHz");
1765 }
1766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1767 return RETURN_OK;
1768#endif
1769}
1770
1771//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1772//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.
1773INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1774{
developer963da0c2022-09-13 15:58:27 +08001775 char cmd[128]={0};
1776 char buf[128]={0};
1777 char temp_output[128] = {0};
1778 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001779 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001780
1781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001782 if (NULL == output_string)
1783 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001784
1785 band = wifi_index_to_band(radioIndex);
1786 if (band == band_2_4) {
1787 strcat(temp_output, "b,g,");
1788 } else if (band == band_5) {
1789 strcat(temp_output, "a,");
1790 }
developer033b37b2022-10-18 11:27:46 +08001791 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001792 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001793 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 +08001794 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001795 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001796 strcat(temp_output, "n,");
1797 }
developer06a01d92022-09-07 16:32:39 +08001798
developer963da0c2022-09-13 15:58:27 +08001799 // vht capabilities
1800 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001801 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 +08001802 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001803 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001804 strcat(temp_output, "ac,");
1805 }
1806 }
1807
1808 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001809 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 +08001810 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001811 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001812 strcat(temp_output, "ax,");
1813 }
1814
developer7c4cd202023-03-01 10:56:29 +08001815 // eht capabilities
1816 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);
1817 _syscmd(cmd, buf, sizeof(buf));
1818 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1819 strcat(temp_output, "be,");
1820 }
1821
developer963da0c2022-09-13 15:58:27 +08001822 // Remove the last comma
1823 if (strlen(temp_output) != 0)
1824 temp_output[strlen(temp_output)-1] = '\0';
1825 strncpy(output_string, temp_output, strlen(temp_output));
1826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001827 return RETURN_OK;
1828}
1829
1830//Get the radio operating mode, and pure mode flag. eg: "ac"
1831//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.
1832INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1833{
1834 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1835 if (NULL == output_string)
1836 return RETURN_ERR;
1837
1838 if (radioIndex == 0) {
1839 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1840 *gOnly = FALSE;
1841 *nOnly = TRUE;
1842 *acOnly = FALSE;
1843 } else {
1844 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1845 *gOnly = FALSE;
1846 *nOnly = FALSE;
1847 *acOnly = FALSE;
1848 }
1849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1850
1851 return RETURN_OK;
1852#if 0
1853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1854 char buf[64] = {0};
1855 char config_file[MAX_BUF_SIZE] = {0};
1856
1857 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1858 return RETURN_ERR;
1859
1860 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1861 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1862
1863 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1864 if (strlen(buf) == 0)
1865 {
1866 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1867 return RETURN_ERR;
1868 }
1869 if(strcmp(buf,"g")==0)
1870 {
1871 wifi_dbg_printf("\nG\n");
1872 *gOnly=TRUE;
1873 *nOnly=FALSE;
1874 *acOnly=FALSE;
1875 }
1876 else if(strcmp(buf,"n")==0)
1877 {
1878 wifi_dbg_printf("\nN\n");
1879 *gOnly=FALSE;
1880 *nOnly=TRUE;
1881 *acOnly=FALSE;
1882 }
1883 else if(strcmp(buf,"ac")==0)
1884 {
1885 wifi_dbg_printf("\nac\n");
1886 *gOnly=FALSE;
1887 *nOnly=FALSE;
1888 *acOnly=TRUE;
1889 }
1890 /* hostapd-5G.conf has "a" as hw_mode */
1891 else if(strcmp(buf,"a")==0)
1892 {
1893 wifi_dbg_printf("\na\n");
1894 *gOnly=FALSE;
1895 *nOnly=FALSE;
1896 *acOnly=FALSE;
1897 }
1898 else
1899 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1900
1901 //for a,n mode
1902 if(radioIndex == 1)
1903 {
1904 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1905 if(strcmp(buf,"1")==0)
1906 {
1907 strncpy(output_string, "n", 1);
1908 *nOnly=FALSE;
1909 }
1910 }
1911
1912 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1913 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1914 return RETURN_OK;
1915#endif
1916}
1917
developerdb744382022-09-13 15:34:54 +08001918INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1919{
1920 char cmd[128] = {0};
1921 char buf[64] = {0};
1922 char config_file[64] = {0};
1923 wifi_band band;
1924
1925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1926 if(NULL == output_string || NULL == pureMode)
1927 return RETURN_ERR;
1928
1929 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001930 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer7c4cd202023-03-01 10:56:29 +08001931 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 +08001932 _syscmd(cmd, buf, sizeof(buf));
1933
1934 band = wifi_index_to_band(radioIndex);
1935 // puremode is a bit map
1936 *pureMode = 0;
1937 if (band == band_2_4) {
1938 strcat(output_string, "b,g");
1939 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1940 if (strstr(buf, "n") != NULL) {
1941 strcat(output_string, ",n");
1942 *pureMode |= WIFI_MODE_N;
1943 }
1944 if (strstr(buf, "ax") != NULL) {
1945 strcat(output_string, ",ax");
1946 *pureMode |= WIFI_MODE_AX;
1947 }
developer7c4cd202023-03-01 10:56:29 +08001948 if (strstr(buf, "be") != NULL) {
1949 strcat(output_string, ",be");
1950 *pureMode |= WIFI_MODE_BE;
1951 }
developerdb744382022-09-13 15:34:54 +08001952 } else if (band == band_5) {
1953 strcat(output_string, "a");
1954 *pureMode |= WIFI_MODE_A;
1955 if (strstr(buf, "n") != NULL) {
1956 strcat(output_string, ",n");
1957 *pureMode |= WIFI_MODE_N;
1958 }
1959 if (strstr(buf, "ac") != NULL) {
1960 strcat(output_string, ",ac");
1961 *pureMode |= WIFI_MODE_AC;
1962 }
1963 if (strstr(buf, "ax") != NULL) {
1964 strcat(output_string, ",ax");
1965 *pureMode |= WIFI_MODE_AX;
1966 }
developer7c4cd202023-03-01 10:56:29 +08001967 if (strstr(buf, "be") != NULL) {
1968 strcat(output_string, ",be");
1969 *pureMode |= WIFI_MODE_BE;
1970 }
developerdb744382022-09-13 15:34:54 +08001971 } else if (band == band_6) {
1972 if (strstr(buf, "ax") != NULL) {
1973 strcat(output_string, "ax");
1974 *pureMode |= WIFI_MODE_AX;
1975 }
developer7c4cd202023-03-01 10:56:29 +08001976 if (strstr(buf, "be") != NULL) {
1977 strcat(output_string, ",be");
1978 *pureMode |= WIFI_MODE_BE;
1979 }
developerdb744382022-09-13 15:34:54 +08001980 }
1981
1982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1983 return RETURN_OK;
1984}
1985
1986// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001987INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1988{
1989 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1990 if (strcmp (channelMode,"11A") == 0)
1991 {
1992 writeBandWidth(radioIndex,"20MHz");
1993 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1994 printf("\nChannel Mode is 802.11a (5GHz)\n");
1995 }
1996 else if (strcmp (channelMode,"11NAHT20") == 0)
1997 {
1998 writeBandWidth(radioIndex,"20MHz");
1999 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2000 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2001 }
2002 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2003 {
2004 writeBandWidth(radioIndex,"40MHz");
2005 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2006 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2007 }
2008 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2009 {
2010 writeBandWidth(radioIndex,"40MHz");
2011 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2012 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2013 }
2014 else if (strcmp (channelMode,"11ACVHT20") == 0)
2015 {
2016 writeBandWidth(radioIndex,"20MHz");
2017 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2018 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2019 }
2020 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2021 {
2022 writeBandWidth(radioIndex,"40MHz");
2023 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2024 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2025 }
2026 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2027 {
2028 writeBandWidth(radioIndex,"40MHz");
2029 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2030 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2031 }
2032 else if (strcmp (channelMode,"11ACVHT80") == 0)
2033 {
2034 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2035 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2036 }
2037 else if (strcmp (channelMode,"11ACVHT160") == 0)
2038 {
2039 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2040 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2041 }
2042 else if (strcmp (channelMode,"11B") == 0)
2043 {
2044 writeBandWidth(radioIndex,"20MHz");
2045 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2046 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2047 }
2048 else if (strcmp (channelMode,"11G") == 0)
2049 {
2050 writeBandWidth(radioIndex,"20MHz");
2051 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2052 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2053 }
2054 else if (strcmp (channelMode,"11NGHT20") == 0)
2055 {
2056 writeBandWidth(radioIndex,"20MHz");
2057 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2058 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2059 }
2060 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2061 {
2062 writeBandWidth(radioIndex,"40MHz");
2063 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2064 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2065 }
2066 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2067 {
2068 writeBandWidth(radioIndex,"40MHz");
2069 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2070 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2071 }
2072 else
2073 {
2074 return RETURN_ERR;
2075 }
2076 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2077
2078 return RETURN_OK;
2079}
2080
developerdb744382022-09-13 15:34:54 +08002081// Set the radio operating mode, and pure mode flag.
2082INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2083{
developer7c4cd202023-03-01 10:56:29 +08002084 int num_hostapd_support_mode = 4; // n, ac, ax, be
developerdb744382022-09-13 15:34:54 +08002085 struct params list[num_hostapd_support_mode];
2086 char config_file[64] = {0};
2087 char bandwidth[16] = {0};
developer7c4cd202023-03-01 10:56:29 +08002088 char supported_mode[32] = {0};
developerdb744382022-09-13 15:34:54 +08002089 int mode_check_bit = 1 << 3; // n mode
developer7c4cd202023-03-01 10:56:29 +08002090 bool eht_support = FALSE;
developerdb744382022-09-13 15:34:54 +08002091
2092 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2093 // Set radio mode
2094 list[0].name = "ieee80211n";
2095 list[1].name = "ieee80211ac";
2096 list[2].name = "ieee80211ax";
developer7c4cd202023-03-01 10:56:29 +08002097 list[3].name = "ieee80211be";
developerdb744382022-09-13 15:34:54 +08002098 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2099
2100 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002101 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002102 list[0].value = "1";
2103 else
2104 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002105 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002106 list[1].value = "1";
2107 else
2108 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002109 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002110 list[2].value = "1";
2111 else
2112 list[2].value = "0";
developer7c4cd202023-03-01 10:56:29 +08002113 if (pureMode & WIFI_MODE_BE)
2114 list[3].value = "1";
2115 else
2116 list[3].value = "0";
2117
2118 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2119 if (strstr(supported_mode, "be") != NULL)
2120 eht_support = TRUE;
2121
2122 if (eht_support)
2123 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2124 else
2125 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode-1);
developerdb744382022-09-13 15:34:54 +08002126
2127 if (channelMode == NULL || strlen(channelMode) == 0)
2128 return RETURN_OK;
2129 // Set bandwidth
2130 if (strstr(channelMode, "40") != NULL)
2131 strcpy(bandwidth, "40MHz");
2132 else if (strstr(channelMode, "80") != NULL)
2133 strcpy(bandwidth, "80MHz");
2134 else if (strstr(channelMode, "160") != NULL)
2135 strcpy(bandwidth, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002136 else if (strstr(channelMode, "320") != NULL)
2137 strcpy(bandwidth, "320MHz");
developerdb744382022-09-13 15:34:54 +08002138 else // 11A, 11B, 11G....
2139 strcpy(bandwidth, "20MHz");
2140
2141 writeBandWidth(radioIndex, bandwidth);
2142 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2143
2144 wifi_reloadAp(radioIndex);
2145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2146
2147 return RETURN_OK;
2148}
2149
developer1d12ebf2022-10-04 15:13:38 +08002150INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2151
2152 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002153 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002154 struct params params = {0};
2155 wifi_band band = band_invalid;
2156
2157 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2158
2159 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002160
2161 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002162 return RETURN_ERR;
2163 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2164 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002165 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2166 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002167
2168 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2169 params.name = "hw_mode";
2170 params.value = hw_mode;
2171 wifi_hostapdWrite(config_file, &params, 1);
2172 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2173
developeref938762022-10-19 17:21:01 +08002174 if (band == band_2_4) {
2175 if (strncmp(hw_mode, "b", 1) == 0) {
2176 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2177 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2178 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2179 snprintf(buf, sizeof(buf), "%s", "1,2");
2180 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2181 } else {
2182 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2183
2184 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2185 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2186 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2187 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2188 }
2189 }
2190
developer1d12ebf2022-10-04 15:13:38 +08002191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2192 return RETURN_OK;
2193}
2194
developere8988ba2022-10-18 17:42:30 +08002195INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2196{
2197 char config_file[64] = {0};
2198 struct params params = {0};
2199 wifi_band band = band_invalid;
2200
2201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2202
2203 band = wifi_index_to_band(radioIndex);
2204
2205 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2206 params.name = "noscan";
2207 params.value = noscan;
2208 wifi_hostapdWrite(config_file, &params, 1);
2209 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2210
2211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2212 return RETURN_OK;
2213}
2214
developer06a01d92022-09-07 16:32:39 +08002215//Get the list of supported channel. eg: "1-11"
2216//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.
2217INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2218{
developer6318ed52022-09-13 15:17:58 +08002219 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002220 if (NULL == output_string)
2221 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002222 char cmd[256] = {0};
2223 char buf[128] = {0};
2224 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002225 int phyId = 0;
2226
developer6318ed52022-09-13 15:17:58 +08002227 // Parse possible channel number and separate them with commas.
2228 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002229 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002230 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002231 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002232 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 +08002233 else
developer033b37b2022-10-18 11:27:46 +08002234 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 +08002235
2236 _syscmd(cmd,buf,sizeof(buf));
2237 strncpy(output_string, buf, sizeof(buf));
2238
2239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2240 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002241}
2242
2243//Get the list for used channel. eg: "1,6,9,11"
2244//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.
2245INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2246{
developerd946fd62022-12-08 18:03:28 +08002247 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002248 char cmd[128] = {0};
2249 char buf[128] = {0};
2250 char config_file[64] = {0};
2251 int channel = 0;
2252 int freq = 0;
2253 int bandwidth = 0;
2254 int center_freq = 0;
2255 int center_channel = 0;
2256 int channel_delta = 0;
2257 wifi_band band = band_invalid;
2258
2259 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2260
developer06a01d92022-09-07 16:32:39 +08002261 if (NULL == output_string)
2262 return RETURN_ERR;
2263
developerac6f1142022-12-20 19:26:35 +08002264 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002265 return RETURN_ERR;
2266 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002267 _syscmd(cmd, buf, sizeof(buf));
2268 if (strlen(buf) == 0) {
2269 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2270 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002271 }
developerf5745ee2022-10-05 16:09:53 +08002272 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2273
2274 if (bandwidth == 20) {
2275 snprintf(output_string, 256, "%d", channel);
2276 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002277 }
developerf5745ee2022-10-05 16:09:53 +08002278
2279 center_channel = ieee80211_frequency_to_channel(center_freq);
2280
2281 band = wifi_index_to_band(radioIndex);
2282 if (band == band_2_4 && bandwidth == 40) {
2283 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2284 memset(buf, 0, sizeof(buf));
2285 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2286
developerf22724d2022-12-22 17:24:14 +08002287 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002288 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002289 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002290 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2291 } else {
2292 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2293 return RETURN_ERR;
2294 }
2295 } else if (band == band_5 || band == band_6){
2296 // 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 +08002297 // 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 +08002298 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002299 memset(output_string, 0, 256);
2300 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2301 // If i is not the last channel, we add a comma.
2302 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2303 strncat(output_string, buf, strlen(buf));
2304 }
developerf5745ee2022-10-05 16:09:53 +08002305 } else
2306 return RETURN_ERR;
2307
2308 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002309 return RETURN_OK;
2310}
2311
2312//Get the running channel number
2313INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2314{
developer5b398df2022-11-17 20:39:48 +08002315 char channel_str[16] = {0};
2316 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002317
developer5b398df2022-11-17 20:39:48 +08002318 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002319 return RETURN_ERR;
2320
developer5b398df2022-11-17 20:39:48 +08002321 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2322 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002323
developer5b398df2022-11-17 20:39:48 +08002324 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002325
developer06a01d92022-09-07 16:32:39 +08002326 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002327}
2328
2329
2330INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2331{
2332 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002333 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002334
2335 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2336 if (NULL == output_ulong)
2337 return RETURN_ERR;
2338
developer06a01d92022-09-07 16:32:39 +08002339 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002340 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2341 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002342 _syscmd(cmd,buf,sizeof(buf));
2343 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2344 if (*output_ulong == 0) {
2345 return RETURN_ERR;
2346 }
2347
2348 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2349 return RETURN_OK;
2350}
2351
2352//Storing the previous channel value
2353INT wifi_storeprevchanval(INT radioIndex)
2354{
2355 char buf[256] = {0};
2356 char output[4]={'\0'};
2357 char config_file[MAX_BUF_SIZE] = {0};
2358 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2359 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2360 if(radioIndex == 0)
2361 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2362 else if(radioIndex == 1)
2363 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2364 system(buf);
2365 Radio_flag = FALSE;
2366 return RETURN_OK;
2367}
2368
2369//Set the running channel number
2370INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2371{
developer76989232022-10-04 14:13:19 +08002372 // We only write hostapd config here
2373 char str_channel[8]={0};
2374 char *list_channel;
2375 char config_file[128] = {0};
2376 char possible_channels[256] = {0};
2377 int max_radio_num = 0;
2378 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002379
developer76989232022-10-04 14:13:19 +08002380 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002381
developer76989232022-10-04 14:13:19 +08002382 // Check valid
2383 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002384
developer76989232022-10-04 14:13:19 +08002385 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2386 list_channel = strtok(possible_channels, ",");
2387 while(true)
developer06a01d92022-09-07 16:32:39 +08002388 {
developer76989232022-10-04 14:13:19 +08002389 if(list_channel == NULL) { // input not in the list
2390 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2391 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002392 }
developer76989232022-10-04 14:13:19 +08002393 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2394 break;
2395 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002396 }
2397
developer76989232022-10-04 14:13:19 +08002398 list.name = "channel";
2399 list.value = str_channel;
2400 wifi_getMaxRadioNumber(&max_radio_num);
2401 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002402 {
developer76989232022-10-04 14:13:19 +08002403 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2404 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002405 }
2406
developer76989232022-10-04 14:13:19 +08002407 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002408 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002409}
developer06a01d92022-09-07 16:32:39 +08002410
2411INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2412{
developer7c4cd202023-03-01 10:56:29 +08002413 struct params list[3];
2414 char str_idx[16] = {0};
2415 char supported_mode[32] = {0};
2416 char config_file[64] = {0};
developer76989232022-10-04 14:13:19 +08002417 int max_num_radios = 0;
2418 wifi_band band = band_invalid;
developer7c4cd202023-03-01 10:56:29 +08002419 bool eht_support = FALSE;
developer76989232022-10-04 14:13:19 +08002420
2421 band = wifi_index_to_band(radioIndex);
2422 if (band == band_2_4)
2423 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002424
developer7c4cd202023-03-01 10:56:29 +08002425 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2426 if (strstr(supported_mode, "be") != NULL)
2427 eht_support = TRUE;
2428
developer30423732022-12-01 16:17:49 +08002429 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002430 list[0].name = "vht_oper_centr_freq_seg0_idx";
2431 list[0].value = str_idx;
2432 list[1].name = "he_oper_centr_freq_seg0_idx";
2433 list[1].value = str_idx;
developer7c4cd202023-03-01 10:56:29 +08002434 list[2].name = "eht_oper_centr_freq_seg0_idx";
2435 list[2].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002436
developer76989232022-10-04 14:13:19 +08002437 wifi_getMaxRadioNumber(&max_num_radios);
2438 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002439 {
developer76989232022-10-04 14:13:19 +08002440 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
developer7c4cd202023-03-01 10:56:29 +08002441 if (eht_support)
2442 wifi_hostapdWrite(config_file, list, 3);
developer76989232022-10-04 14:13:19 +08002443 else
2444 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002445 }
2446
2447 return RETURN_OK;
2448}
2449
2450//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2451//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2452INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2453{
2454 //Set to wifi config only. Wait for wifi reset to apply.
2455 char buf[256] = {0};
2456 char str_channel[256] = {0};
2457 int count = 0;
2458 ULONG Value = 0;
2459 FILE *fp = NULL;
2460 if(enable == TRUE)
2461 {
developer06a01d92022-09-07 16:32:39 +08002462 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002463 }
developer5884e982022-10-06 10:52:50 +08002464 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002465}
2466
developer0b246d12022-09-30 15:24:20 +08002467INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2468{
2469 if (output_bool == NULL)
2470 return RETURN_ERR;
2471
2472 *output_bool = TRUE;
2473
2474 return RETURN_OK;
2475}
2476
developer06a01d92022-09-07 16:32:39 +08002477INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2478{
2479 if (NULL == output_bool)
2480 return RETURN_ERR;
2481 *output_bool=FALSE;
2482 return RETURN_OK;
2483}
2484
2485INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2486{
2487 if (NULL == output_bool)
2488 return RETURN_ERR;
2489 *output_bool=FALSE;
2490 return RETURN_OK;
2491}
2492
2493INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2494{
2495 //Set to wifi config only. Wait for wifi reset to apply.
2496 return RETURN_OK;
2497}
2498
2499INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2500{
2501 return RETURN_OK;
2502}
2503
2504INT wifi_factoryResetAP(int apIndex)
2505{
developer838cca92022-10-03 13:19:57 +08002506 char ap_config_file[64] = {0};
2507 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002508 char buf[128] = {0};
developer89df4502023-02-16 20:45:02 +08002509 int max_radio_num = 0;
developer838cca92022-10-03 13:19:57 +08002510
developer06a01d92022-09-07 16:32:39 +08002511 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002512
2513 wifi_setApEnable(apIndex, FALSE);
2514 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2515 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002516 _syscmd(cmd, buf, sizeof(buf));
developer89df4502023-02-16 20:45:02 +08002517 wifi_getMaxRadioNumber(&max_radio_num);
2518 if (apIndex <= max_radio_num) // The ap is default radio interface, we should default up it.
2519 wifi_setApEnable(apIndex, TRUE);
developer838cca92022-10-03 13:19:57 +08002520
developer06a01d92022-09-07 16:32:39 +08002521 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002522
developer06a01d92022-09-07 16:32:39 +08002523 return RETURN_OK;
2524}
2525
2526//To set Band Steering AP group
2527//To-do
2528INT wifi_setBandSteeringApGroup(char *ApGroup)
2529{
2530 return RETURN_OK;
2531}
2532
developer1e5aa162022-09-13 16:06:24 +08002533INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2534{
2535 char config_file[128] = {'\0'};
2536 char buf[128] = {'\0'};
2537
2538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2539 if (dtimInterval == NULL)
2540 return RETURN_ERR;
2541
2542 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2543 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2544
2545 if (strlen(buf) == 0) {
2546 *dtimInterval = 2;
2547 } else {
2548 *dtimInterval = strtoul(buf, NULL, 10);
2549 }
2550
2551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2552 return RETURN_OK;
2553}
2554
developer06a01d92022-09-07 16:32:39 +08002555INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2556{
developer5f222492022-09-13 15:21:52 +08002557 struct params params={0};
2558 char config_file[MAX_BUF_SIZE] = {'\0'};
2559 char buf[MAX_BUF_SIZE] = {'\0'};
2560
2561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2562 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002563 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002564 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002565 }
2566
2567 params.name = "dtim_period";
2568 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2569 params.value = buf;
2570
2571 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2572 wifi_hostapdWrite(config_file, &params, 1);
2573 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2574
2575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2576 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002577}
2578
2579//Check if the driver support the Dfs
2580INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2581{
developer78a15382022-11-02 10:57:40 +08002582 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002583 if (NULL == output_bool)
2584 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002585 *output_bool=FALSE;
2586
2587 band = wifi_index_to_band(radioIndex);
2588 if (band == band_5)
2589 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002590 return RETURN_OK;
2591}
2592
2593//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.
2594//The value of this parameter is a comma seperated list of channel number
2595INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2596{
2597 if (NULL == output_pool)
2598 return RETURN_ERR;
2599 if (radioIndex==1)
2600 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2601 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2602
2603 return RETURN_OK;
2604}
2605
2606INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2607{
2608 //Set to wifi config. And apply instantly.
2609 return RETURN_OK;
2610}
2611
2612INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2613{
2614 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2615 return RETURN_ERR;
2616 *output_interval_seconds=1800;
2617 *output_dwell_milliseconds=40;
2618
2619 return RETURN_OK;
2620}
2621
2622INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2623{
2624 //Set to wifi config. And apply instantly.
2625 return RETURN_OK;
2626}
2627
developerbfc18512022-10-05 17:54:28 +08002628INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2629{
2630 if (output_bool == NULL)
2631 return RETURN_ERR;
2632 *output_bool = true;
2633 return RETURN_OK;
2634}
2635
2636INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2637{
2638 return RETURN_OK;
2639}
2640
developer06a01d92022-09-07 16:32:39 +08002641//Get the Dfs enable status
2642INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2643{
developer9964b5b2022-09-13 15:59:34 +08002644 char buf[16] = {0};
2645 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002646
2647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2648
developer30423732022-12-01 16:17:49 +08002649 if (output_bool == NULL)
2650 return RETURN_ERR;
2651
developer9964b5b2022-09-13 15:59:34 +08002652 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002653 f = fopen(DFS_ENABLE_FILE, "r");
2654 if (f != NULL) {
2655 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002656 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002657 *output_bool = FALSE;
2658 fclose(f);
2659 }
2660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002661 return RETURN_OK;
2662}
2663
2664//Set the Dfs enable status
2665INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2666{
developer9964b5b2022-09-13 15:59:34 +08002667 char config_file[128] = {0};
2668 FILE *f = NULL;
2669 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002670
2671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2672
developer9964b5b2022-09-13 15:59:34 +08002673 f = fopen(DFS_ENABLE_FILE, "w");
2674 if (f == NULL)
2675 return RETURN_ERR;
2676 fprintf(f, "%d", enable);
2677 fclose(f);
2678
2679 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002680 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002681 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2682 wifi_hostapdWrite(config_file, &params, 1);
2683 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2684
2685 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2686
developer9964b5b2022-09-13 15:59:34 +08002687 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002688 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002689}
2690
2691//Check if the driver support the AutoChannelRefreshPeriod
2692INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2693{
2694 if (NULL == output_bool)
2695 return RETURN_ERR;
2696 *output_bool=FALSE; //not support
2697
2698 return RETURN_OK;
2699}
2700
2701//Get the ACS refresh period in seconds
2702INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2703{
2704 if (NULL == output_ulong)
2705 return RETURN_ERR;
2706 *output_ulong=300;
2707
2708 return RETURN_OK;
2709}
2710
2711//Set the ACS refresh period in seconds
2712INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2713{
2714 return RETURN_ERR;
2715}
2716
developer7c4cd202023-03-01 10:56:29 +08002717INT getEHT320ChannelBandwidthSet(int radioIndex, int *BandwidthSet)
2718{
2719 int center_channel = 0;
2720 char config_file[32] = {0};
2721 char buf[32] = {0};
2722
2723 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2724 wifi_hostapdRead(config_file, "eht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2725
2726 center_channel = strtoul(buf, NULL, 10);
2727 center_channel += 1; // Add 1 to become muiltiple of 16
2728 if (center_channel % 64 == 32)
2729 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_1MHZ;
2730 else if (center_channel % 64 == 0)
2731 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_2MHZ;
2732 else
2733 return RETURN_ERR;
2734 return RETURN_OK;
2735}
2736
developer06a01d92022-09-07 16:32:39 +08002737//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2738//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.
2739INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2740{
developer72ec5572023-01-05 16:27:13 +08002741 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002742 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002743 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002744 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002745 wifi_band band;
developer70490032022-09-13 15:45:20 +08002746
2747 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2748
developer06a01d92022-09-07 16:32:39 +08002749 if (NULL == output_string)
2750 return RETURN_ERR;
2751
developer70490032022-09-13 15:45:20 +08002752 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2753 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002754
developer70490032022-09-13 15:45:20 +08002755 if (radio_enable != TRUE)
2756 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002757
developerfa41b1f2023-01-06 10:25:51 +08002758 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002759 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002760 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002761 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2762 snprintf(output_string, 64, "20MHz");
2763 else
2764 snprintf(output_string, 64, "40MHz");
2765
2766 } else {
2767 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2768 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2769 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2770 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2771 if (strncmp(buf, "0", 1) == 0)
2772 snprintf(output_string, 64, "20MHz");
2773 else
2774 snprintf(output_string, 64, "40MHz");
2775
2776 } else if (strncmp(buf, "1", 1) == 0)
2777 snprintf(output_string, 64, "80MHz");
developer7c4cd202023-03-01 10:56:29 +08002778 else if (strncmp(buf, "2", 1) == 0) {
developer72ec5572023-01-05 16:27:13 +08002779 snprintf(output_string, 64, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002780 wifi_hostapdRead(config_file, "eht_oper_chwidth", buf, sizeof(buf));
2781 if (strncmp(buf, "9", 1) == 0) {
2782 int BandwidthSet = 0;
2783 if (getEHT320ChannelBandwidthSet(radioIndex, &BandwidthSet) != RETURN_OK)
2784 return RETURN_ERR;
2785 if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_1MHZ)
2786 snprintf(output_string, 64, "320-1MHz");
2787 else if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_2MHZ)
2788 snprintf(output_string, 64, "320-2MHz");
2789 }
2790 }
developer06a01d92022-09-07 16:32:39 +08002791 }
developer72ec5572023-01-05 16:27:13 +08002792
developer06a01d92022-09-07 16:32:39 +08002793 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002794
2795 return RETURN_OK;
2796}
2797
2798//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002799INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002800{
developerf7a466e2022-09-29 11:55:56 +08002801 char config_file[128];
2802 char set_value[16];
developer7c4cd202023-03-01 10:56:29 +08002803 char supported_mode[32] = {0};
2804 struct params params[3];
developerf7a466e2022-09-29 11:55:56 +08002805 int max_radio_num = 0;
developer7c4cd202023-03-01 10:56:29 +08002806 bool eht_support = FALSE;
developerf7a466e2022-09-29 11:55:56 +08002807
developer06a01d92022-09-07 16:32:39 +08002808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002809
developerf7a466e2022-09-29 11:55:56 +08002810 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002811 return RETURN_ERR;
2812
developer7c4cd202023-03-01 10:56:29 +08002813 if(strstr(bandwidth,"160") != NULL || strstr(bandwidth,"320") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002814 strcpy(set_value, "2");
2815 else if(strstr(bandwidth,"80") != NULL)
2816 strcpy(set_value, "1");
2817 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2818 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002819 else if (strstr(bandwidth, "Auto") != NULL)
2820 return RETURN_OK;
2821 else {
developerf7a466e2022-09-29 11:55:56 +08002822 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002823 return RETURN_ERR;
2824 }
2825
developer7c4cd202023-03-01 10:56:29 +08002826 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2827 if (strstr(supported_mode, "be") != NULL)
2828 eht_support = TRUE;
2829
developerf7a466e2022-09-29 11:55:56 +08002830 params[0].name = "vht_oper_chwidth";
2831 params[0].value = set_value;
2832 params[1].name = "he_oper_chwidth";
2833 params[1].value = set_value;
developer7c4cd202023-03-01 10:56:29 +08002834 params[2].name = "eht_oper_chwidth";
2835 if (strstr(bandwidth,"320") != NULL) // We set oper_chwidth to 9 for EHT320
2836 params[2].value = "9";
2837 else
2838 params[2].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002839
developerf7a466e2022-09-29 11:55:56 +08002840 wifi_getMaxRadioNumber(&max_radio_num);
2841 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002842 {
developer7c4cd202023-03-01 10:56:29 +08002843 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2844 if (eht_support == TRUE)
2845 wifi_hostapdWrite(config_file, params, 3);
2846 else
2847 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002848 }
2849
2850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2851 return RETURN_OK;
2852}
2853
2854//Getting current radio extension channel
2855INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2856{
2857 CHAR buf[150] = {0};
2858 CHAR cmd[150] = {0};
2859 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2860 _syscmd(cmd, buf, sizeof(buf));
2861 if(NULL != strstr(buf,"HT40+"))
2862 strcpy(Value,"AboveControlChannel");
2863 else if(NULL != strstr(buf,"HT40-"))
2864 strcpy(Value,"BelowControlChannel");
2865 return RETURN_OK;
2866}
2867
2868//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2869//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.
2870INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2871{
developerfa41b1f2023-01-06 10:25:51 +08002872 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002873 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002874
2875 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002876 return RETURN_ERR;
2877
developerfa41b1f2023-01-06 10:25:51 +08002878 band = wifi_index_to_band(radioIndex);
2879 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002880 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002881
2882 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2883
2884 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002885 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002886
2887 return RETURN_OK;
2888}
2889
developer57fa24a2023-03-15 17:25:07 +08002890// This function handle 20MHz to remove HT40+/- in hostapd config, other bandwidths are handled in wifi_setRadioExtChannel.
2891INT wifi_RemoveRadioExtChannel(INT radioIndex, CHAR *ext_str)
2892{
2893 struct params params={0};
2894 char config_file[64] = {0};
2895 char ht_capab[128]={0};
2896 char buf[128] = {0};
2897 char cmd[128] = {0};
2898 int max_radio_num =0;
2899 bool stbcEnable = FALSE;
2900
2901 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2902 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2903 _syscmd(cmd, buf, sizeof(buf));
2904 if (strlen(buf) != 0)
2905 stbcEnable = TRUE;
2906
2907 strcpy(ht_capab, HOSTAPD_HT_CAPAB);
2908 params.value = ht_capab;
2909 params.name = "ht_capab";
2910
2911 wifi_getMaxRadioNumber(&max_radio_num);
2912 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2913 {
2914 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2915 wifi_hostapdWrite(config_file, &params, 1);
developer57fa24a2023-03-15 17:25:07 +08002916 }
developer8d7d0862023-05-18 16:50:23 +08002917 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer57fa24a2023-03-15 17:25:07 +08002918 return RETURN_OK;
2919}
2920
developer06a01d92022-09-07 16:32:39 +08002921//Set the extension channel.
2922INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer72ec5572023-01-05 16:27:13 +08002923{
developer06a01d92022-09-07 16:32:39 +08002924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002925 struct params params={0};
2926 char config_file[64] = {0};
2927 char ext_channel[128]={0};
2928 char buf[128] = {0};
2929 char cmd[128] = {0};
2930 int max_radio_num =0, ret = 0, bandwidth = 0;
developer72ec5572023-01-05 16:27:13 +08002931 unsigned long channel = 0;
developerfa41b1f2023-01-06 10:25:51 +08002932 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002933 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002934 wifi_band band;
2935
2936 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2937 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2938 _syscmd(cmd, buf, sizeof(buf));
2939 if (strlen(buf) != 0)
2940 stbcEnable = TRUE;
developer57fa24a2023-03-15 17:25:07 +08002941
2942 // readBandWidth get empty file will return error, that means we don't set new bandwidth
2943 if (readBandWidth(radioIndex, buf) != RETURN_OK) {
2944 // Get current bandwidth
2945 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2946 return RETURN_ERR;
2947 }
developerfa41b1f2023-01-06 10:25:51 +08002948 bandwidth = strtol(buf, NULL, 10);
2949 // TDK expected to get error with 20MHz
developer57fa24a2023-03-15 17:25:07 +08002950 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developerfa41b1f2023-01-06 10:25:51 +08002951 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2952 return RETURN_ERR;
2953
2954 band = wifi_index_to_band(radioIndex);
2955 if (band == band_invalid)
2956 return RETURN_ERR;
2957
2958 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2959 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002960
developer72ec5572023-01-05 16:27:13 +08002961 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2962 ret = util_get_sec_chan_offset(channel, buf);
2963 if (ret == -EINVAL)
2964 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002965
2966 if(NULL!= strstr(string,"Above")) {
developer72ec5572023-01-05 16:27:13 +08002967 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
2968 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002969 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08002970 } else if(NULL!= strstr(string,"Below")) {
developer72ec5572023-01-05 16:27:13 +08002971 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == 1))
2972 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002973 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08002974 } else {
developer57fa24a2023-03-15 17:25:07 +08002975 fprintf(stderr, "%s: unknow extchannel %s\n", __func__, string);
2976 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002977 }
developer06a01d92022-09-07 16:32:39 +08002978
2979 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002980
2981 wifi_getMaxRadioNumber(&max_radio_num);
2982 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002983 {
developer033b37b2022-10-18 11:27:46 +08002984 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002985 wifi_hostapdWrite(config_file, &params, 1);
2986 }
developer8d7d0862023-05-18 16:50:23 +08002987 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer06a01d92022-09-07 16:32:39 +08002988
2989 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2990 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2991 return RETURN_OK;
2992}
2993
2994//Get the guard interval value. eg "400nsec" or "800nsec"
2995//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.
2996INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2997{
developer454b9462022-09-13 15:29:16 +08002998 wifi_guard_interval_t GI;
2999
3000 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3001
3002 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08003003 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08003004
3005 if (GI == wifi_guard_interval_400)
3006 strcpy(output_string, "400nsec");
3007 else if (GI == wifi_guard_interval_800)
3008 strcpy(output_string, "800nsec");
3009 else if (GI == wifi_guard_interval_1600)
3010 strcpy(output_string, "1600nsec");
3011 else if (GI == wifi_guard_interval_3200)
3012 strcpy(output_string, "3200nsec");
3013 else
developer78a15382022-11-02 10:57:40 +08003014 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08003015
developer454b9462022-09-13 15:29:16 +08003016 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003017 return RETURN_OK;
3018}
3019
3020//Set the guard interval value.
3021INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3022{
developer454b9462022-09-13 15:29:16 +08003023 wifi_guard_interval_t GI;
3024 int ret = 0;
3025
3026 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3027
3028 if (strcmp(string, "400nsec") == 0)
3029 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08003030 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08003031 GI = wifi_guard_interval_800;
3032 else if (strcmp(string , "1600nsec") == 0)
3033 GI = wifi_guard_interval_1600;
3034 else if (strcmp(string , "3200nsec") == 0)
3035 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08003036 else
3037 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08003038
3039 ret = wifi_setGuardInterval(radioIndex, GI);
3040
3041 if (ret == RETURN_ERR) {
3042 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3043 return RETURN_ERR;
3044 }
3045
3046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3047 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003048}
3049
3050//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3051INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3052{
developerf49437e2022-09-29 19:58:21 +08003053 char buf[32]={0};
3054 char mcs_file[64] = {0};
3055 char cmd[64] = {0};
3056 int mode_bitmap = 0;
3057
3058 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3059 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08003060 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08003061 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3062
3063 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3064 _syscmd(cmd, buf, sizeof(buf));
3065 if (strlen(buf) > 0)
3066 *output_int = strtol(buf, NULL, 10);
3067 else {
3068 // output the max MCS for the current radio mode
3069 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3070 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3071 return RETURN_ERR;
3072 }
3073 if (mode_bitmap & WIFI_MODE_AX) {
3074 *output_int = 11;
3075 } else if (mode_bitmap & WIFI_MODE_AC) {
3076 *output_int = 9;
3077 } else if (mode_bitmap & WIFI_MODE_N) {
3078 *output_int = 7;
3079 }
3080 }
3081 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003082
3083 return RETURN_OK;
3084}
3085
3086//Set the Modulation Coding Scheme index
3087INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3088{
developerf49437e2022-09-29 19:58:21 +08003089 // 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).
3090 char config_file[64] = {0};
3091 char set_value[16] = {0};
3092 char mcs_file[32] = {0};
3093 wifi_band band = band_invalid;
3094 struct params set_config = {0};
3095 FILE *f = NULL;
3096
3097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3098
3099 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3100
developer78a15382022-11-02 10:57:40 +08003101 // -1 means auto
3102 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08003103 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3104 return RETURN_ERR;
3105 }
3106
developer78a15382022-11-02 10:57:40 +08003107 if (MCS > 9 || MCS == -1)
3108 strcpy(set_value, "2");
3109 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08003110 strcpy(set_value, "1");
3111 else
developer78a15382022-11-02 10:57:40 +08003112 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08003113
3114 set_config.name = "he_basic_mcs_nss_set";
3115 set_config.value = set_value;
3116
3117 wifi_hostapdWrite(config_file, &set_config, 1);
3118 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3119
3120 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3121 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3122 f = fopen(mcs_file, "w");
3123 if (f == NULL) {
3124 fprintf(stderr, "%s: fopen failed\n", __func__);
3125 return RETURN_ERR;
3126 }
3127 fprintf(f, "%d", MCS);
3128 fclose(f);
3129
3130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3131 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003132}
3133
3134//Get supported Transmit Power list, eg : "0,25,50,75,100"
3135//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.
3136INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3137{
3138 if (NULL == output_list)
3139 return RETURN_ERR;
developer5c97d532023-09-28 11:19:30 +08003140 snprintf(output_list, 64,"0,12,25,50,75,100");
developer06a01d92022-09-07 16:32:39 +08003141 return RETURN_OK;
3142}
3143
developer5c97d532023-09-28 11:19:30 +08003144// Get current Transmit Power in percent
developer06a01d92022-09-07 16:32:39 +08003145INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3146{
developer5c97d532023-09-28 11:19:30 +08003147 char cmd[128]={'\0'};
3148 char buf[128]={'\0'};
3149 int phyIndex = -1;
3150 bool enabled = false;
3151 int cur_tx_dbm = 0;
3152
developera5005b62022-09-13 15:43:35 +08003153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003154
developera5005b62022-09-13 15:43:35 +08003155 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003156 return RETURN_ERR;
3157
developer5c97d532023-09-28 11:19:30 +08003158 phyIndex = radio_index_to_phy(radioIndex);
3159
3160 // Get the maximum tx power of the device
3161 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
3162 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developer06a01d92022-09-07 16:32:39 +08003163 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003164 if (strcmp(buf, "enable") == 0)
3165 enabled = true;
developer06a01d92022-09-07 16:32:39 +08003166
developer5c97d532023-09-28 11:19:30 +08003167 if (!enabled) {
3168 *output_ulong = 100;
3169 return RETURN_OK;
3170 }
developera5005b62022-09-13 15:43:35 +08003171
developer5c97d532023-09-28 11:19:30 +08003172 memset(cmd, 0, sizeof(cmd));
3173 memset(buf, 0, sizeof(buf));
3174 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
3175 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
3176 _syscmd(cmd, buf, sizeof(buf));
3177 cur_tx_dbm = strtol(buf, NULL, 10);
3178
3179 switch (cur_tx_dbm) {
3180 case 0:
3181 *output_ulong = 100; // range 91-100
3182 break;
3183 case 1:
3184 *output_ulong = 75; // range 61-90
3185 break;
3186 case 3:
3187 *output_ulong = 50; // range 31-60
3188 break;
3189 case 6:
3190 *output_ulong = 25; // range 16-30
3191 break;
3192 case 9:
3193 *output_ulong = 12; // range 10-15
3194 break;
3195 case 12:
3196 *output_ulong = 6; // range 1-9
3197 break;
3198 default:
3199 *output_ulong = 100; // 0
3200 }
3201
developer06a01d92022-09-07 16:32:39 +08003202 return RETURN_OK;
3203}
3204
developer5c97d532023-09-28 11:19:30 +08003205// TransmitPower: the the percentage relative to the maximum power,
3206// only support 0,12,25,50,75,100, But 0 means disable Power limit,
3207// so the power is 100%
developer06a01d92022-09-07 16:32:39 +08003208INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3209{
developerd946fd62022-12-08 18:03:28 +08003210 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003211 char *support;
developer06a01d92022-09-07 16:32:39 +08003212 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003213 char buf[128]={0};
3214 char txpower_str[64] = {0};
developer033b37b2022-10-18 11:27:46 +08003215 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003216
3217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003218
developerac6f1142022-12-20 19:26:35 +08003219 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003220 return RETURN_ERR;
developera5005b62022-09-13 15:43:35 +08003221
3222 // Get the Tx power supported list and check that is the input in the list
3223 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3224 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3225 support = strtok(buf, ",");
3226 while(true)
3227 {
3228 if(support == NULL) { // input not in the list
3229 wifi_dbg_printf("Input value is invalid.\n");
3230 return RETURN_ERR;
3231 }
3232 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3233 break;
3234 }
3235 support = strtok(NULL, ",");
3236 }
developer5c97d532023-09-28 11:19:30 +08003237
developer033b37b2022-10-18 11:27:46 +08003238 phyId = radio_index_to_phy(radioIndex);
developer5c97d532023-09-28 11:19:30 +08003239 snprintf(cmd, sizeof(cmd), "echo %lu > /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_level",
3240 TransmitPower, phyId);
developera5005b62022-09-13 15:43:35 +08003241 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003242
developera5005b62022-09-13 15:43:35 +08003243 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003244
3245 return RETURN_OK;
3246}
3247
3248//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3249INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3250{
3251 if (NULL == Supported)
3252 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003253 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003254
3255 return RETURN_OK;
3256}
3257
3258//Get 80211h feature enable
3259INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3260{
developer3885fec2022-09-13 15:13:47 +08003261 char buf[64]={'\0'};
3262 char config_file[64] = {'\0'};
3263
3264 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3265 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003266 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003267
3268 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3269 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003270
developer3885fec2022-09-13 15:13:47 +08003271 if (strncmp(buf, "1", 1) == 0)
3272 *enable = TRUE;
3273 else
3274 *enable = FALSE;
3275
3276 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003277 return RETURN_OK;
3278}
3279
3280//Set 80211h feature enable
3281INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3282{
developer3885fec2022-09-13 15:13:47 +08003283 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3284 struct params params={'\0'};
3285 char config_file[MAX_BUF_SIZE] = {0};
3286
3287 params.name = "ieee80211h";
3288
3289 if (enable) {
3290 params.value = "1";
3291 } else {
3292 params.value = "0";
3293 }
3294
3295 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3296 wifi_hostapdWrite(config_file, &params, 1);
3297
3298 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3299 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3300 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003301}
3302
3303//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.
3304INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3305{
3306 if (NULL == output)
3307 return RETURN_ERR;
3308 *output=100;
3309
3310 return RETURN_OK;
3311}
3312
3313//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.
3314INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3315{
3316 if (NULL == output)
3317 return RETURN_ERR;
3318 *output = -99;
3319
3320 return RETURN_OK;
3321}
3322
3323INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3324{
3325 return RETURN_ERR;
3326}
3327
3328
3329//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3330INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3331{
developerd946fd62022-12-08 18:03:28 +08003332 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003333 char cmd[MAX_BUF_SIZE]={'\0'};
3334 char buf[MAX_CMD_SIZE]={'\0'};
3335
3336 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3337 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003338 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003339
developerac6f1142022-12-20 19:26:35 +08003340 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003341 return RETURN_ERR;
3342 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 +08003343 _syscmd(cmd, buf, sizeof(buf));
3344 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003345
developer5f222492022-09-13 15:21:52 +08003346 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003347 return RETURN_OK;
3348}
3349
3350INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3351{
developer5f222492022-09-13 15:21:52 +08003352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3353 struct params params={'\0'};
3354 char buf[MAX_BUF_SIZE] = {'\0'};
3355 char config_file[MAX_BUF_SIZE] = {'\0'};
3356
developer5b398df2022-11-17 20:39:48 +08003357 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3358 return RETURN_ERR;
3359
developer5f222492022-09-13 15:21:52 +08003360 params.name = "beacon_int";
3361 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3362 params.value = buf;
3363
3364 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3365 wifi_hostapdWrite(config_file, &params, 1);
3366
3367 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3369 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003370}
3371
3372//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.
3373INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3374{
developer06a01d92022-09-07 16:32:39 +08003375 //TODO: need to revisit below implementation
3376 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003377 char temp_output[128] = {0};
3378 char temp_TransmitRates[64] = {0};
3379 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003380
3381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3382 if (NULL == output)
3383 return RETURN_ERR;
3384 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003385 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3386
3387 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3388 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3389 } else {
3390 temp = strtok(temp_TransmitRates," ");
3391 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003392 {
developere9d0abd2022-09-13 15:40:57 +08003393 // Convert 100 kbps to Mbps
3394 temp[strlen(temp)-1]=0;
3395 if((temp[0]=='5') && (temp[1]=='\0'))
3396 {
3397 temp="5.5";
3398 }
3399 strcat(temp_output,temp);
3400 temp = strtok(NULL," ");
3401 if(temp!=NULL)
3402 {
3403 strcat(temp_output,",");
3404 }
developer06a01d92022-09-07 16:32:39 +08003405 }
developere9d0abd2022-09-13 15:40:57 +08003406 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003407 }
developer06a01d92022-09-07 16:32:39 +08003408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003409 return RETURN_OK;
3410}
3411
3412INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3413{
3414 char *temp;
3415 char temp1[128];
3416 char temp_output[128];
3417 char temp_TransmitRates[128];
3418 char set[128];
3419 char sub_set[128];
3420 int set_count=0,subset_count=0;
3421 int set_index=0,subset_index=0;
3422 char *token;
3423 int flag=0, i=0;
3424 struct params params={'\0'};
3425 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003426 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003427
3428 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3429 if(NULL == TransmitRates)
3430 return RETURN_ERR;
3431 strcpy(sub_set,TransmitRates);
3432
3433 //Allow only supported Data transmit rate to be set
3434 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3435 token = strtok(sub_set,",");
3436 while( token != NULL ) /* split the basic rate to be set, by comma */
3437 {
3438 sub_set[subset_count]=atoi(token);
3439 subset_count++;
3440 token=strtok(NULL,",");
3441 }
3442 token=strtok(set,",");
3443 while(token!=NULL) /* split the supported rate by comma */
3444 {
3445 set[set_count]=atoi(token);
3446 set_count++;
3447 token=strtok(NULL,",");
3448 }
3449 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3450 {
3451 for(set_index=0;set_index < set_count;set_index++)
3452 {
3453 flag=0;
3454 if(sub_set[subset_index]==set[set_index])
3455 break;
3456 else
3457 flag=1; /* No match found */
3458 }
3459 if(flag==1)
3460 return RETURN_ERR; //If value not found return Error
3461 }
3462 strcpy(temp_TransmitRates,TransmitRates);
3463
3464 for(i=0;i<strlen(temp_TransmitRates);i++)
3465 {
3466 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003467 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003468 {
3469 continue;
3470 }
3471 else
3472 {
3473 return RETURN_ERR;
3474 }
3475 }
3476 strcpy(temp_output,"");
3477 temp = strtok(temp_TransmitRates,",");
3478 while(temp!=NULL)
3479 {
3480 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003481 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003482 {
developeref938762022-10-19 17:21:01 +08003483 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003484 {
3485 return RETURN_ERR;
3486 }
3487 }
3488
3489 if(strcmp(temp,"5.5")==0)
3490 {
3491 strcpy(temp1,"55");
3492 }
3493 else
3494 {
3495 strcat(temp1,"0");
3496 }
3497 strcat(temp_output,temp1);
3498 temp = strtok(NULL,",");
3499 if(temp!=NULL)
3500 {
3501 strcat(temp_output," ");
3502 }
3503 }
3504 strcpy(TransmitRates,temp_output);
3505
3506 params.name= "basic_rates";
3507 params.value =TransmitRates;
3508
3509 wifi_dbg_printf("\n%s:",__func__);
3510 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3511 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3512 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3513 wifi_hostapdWrite(config_file,&params,1);
3514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3515 return RETURN_OK;
3516}
3517
3518//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003519INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003520{
3521 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3522 FILE *fp = NULL;
3523 char path[256] = {0}, output_string[256] = {0};
3524 int count = 0;
3525 char *interface = NULL;
3526
3527 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3528 if (fp == NULL)
3529 {
3530 printf("Failed to run command in Function %s\n", __FUNCTION__);
3531 return RETURN_ERR;
3532 }
3533 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3534 {
3535 interface = strchr(path, '=');
3536
3537 if (interface != NULL)
3538 {
3539 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003540 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003541 interface_name[count] = output_string[count];
3542
3543 interface_name[count] = '\0';
3544 }
3545 }
3546 pclose(fp);
3547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3548 return RETURN_OK;
3549}
3550
3551INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3552{
3553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3554 output_struct->radio_BytesSent = 0;
3555 output_struct->radio_BytesReceived = 0;
3556 output_struct->radio_PacketsSent = 0;
3557 output_struct->radio_PacketsReceived = 0;
3558 output_struct->radio_ErrorsSent = 0;
3559 output_struct->radio_ErrorsReceived = 0;
3560 output_struct->radio_DiscardPacketsSent = 0;
3561 output_struct->radio_DiscardPacketsReceived = 0;
3562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3563 return RETURN_OK;
3564}
3565
3566
3567INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3568{
3569 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3570 CHAR buf[MAX_CMD_SIZE] = {0};
3571 CHAR Value[MAX_BUF_SIZE] = {0};
3572 FILE *fp = NULL;
3573
3574 if (ifname == NULL || strlen(ifname) <= 1)
3575 return RETURN_OK;
3576
3577 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3578 system(buf);
3579
3580 fp = fopen("/tmp/Radio_Stats.txt", "r");
3581 if(fp == NULL)
3582 {
3583 printf("/tmp/Radio_Stats.txt not exists \n");
3584 return RETURN_ERR;
3585 }
3586 fclose(fp);
3587
3588 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3589 File_Reading(buf, Value);
3590 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3591
3592 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3593 File_Reading(buf, Value);
3594 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3595
3596 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3597 File_Reading(buf, Value);
3598 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3599
3600 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3601 File_Reading(buf, Value);
3602 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3603
3604 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3605 File_Reading(buf, Value);
3606 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3607
3608 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3609 File_Reading(buf, Value);
3610 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3611
3612 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3613 File_Reading(buf, Value);
3614 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3615
3616 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3617 File_Reading(buf, Value);
3618 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3619
3620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3621 return RETURN_OK;
3622}
3623
3624INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3625{
3626 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3627 CHAR buf[MAX_CMD_SIZE] = {0};
3628 FILE *fp = NULL;
3629 INT count = 0;
3630
3631 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3632 {
3633 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3634 File_Reading(buf, status);
3635 }
3636 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3637 return RETURN_OK;
3638}
3639
3640//Get detail radio traffic static info
3641INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3642{
3643
3644#if 0
3645 //ifconfig radio_x
3646 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3647 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3648 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3649 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3650
3651 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3652 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3653 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.
3654 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.
3655
3656 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3657 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].
3658 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3659 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.
3660 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
3661 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
3662 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
3663 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
3664 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
3665
3666 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
3667 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
3668 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
3669 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.
3670
3671 return RETURN_OK;
3672#endif
3673
developera91d99f2022-09-29 15:59:10 +08003674 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003675 BOOL iface_status = FALSE;
3676 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003677
3678 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3679 if (NULL == output_struct)
3680 return RETURN_ERR;
3681
developerac6f1142022-12-20 19:26:35 +08003682 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08003683 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003684
developera91d99f2022-09-29 15:59:10 +08003685 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003686
developera91d99f2022-09-29 15:59:10 +08003687 if (iface_status == TRUE)
3688 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3689 else
3690 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003691
developera91d99f2022-09-29 15:59:10 +08003692 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3693 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3694 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3695 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3696 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3697 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3698 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3699 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003700
3701 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3702 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].
3703 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3704 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.
3705 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
3706 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
3707 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
3708 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
3709 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
3710
3711 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
3712 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
3713 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
3714 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.
3715
3716 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3717
3718 return RETURN_OK;
3719}
3720
3721//Set radio traffic static Measureing rules
3722INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3723{
3724 //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
3725 // Else, save the MeasuringRate and MeasuringInterval for future usage
3726
3727 return RETURN_OK;
3728}
3729
3730//To start or stop RadioTrafficStats
3731INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3732{
3733 //zqiu: If the RadioTrafficStats process running
3734 // if(enable)
3735 // return RETURN_OK.
3736 // else
3737 // Stop RadioTrafficStats process
3738 // Else
3739 // if(enable)
3740 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3741 // else
3742 // return RETURN_OK.
3743
3744 return RETURN_OK;
3745}
3746
3747//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
3748INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3749{
3750 //zqiu: Please ignor signalIndex.
3751 if (NULL == SignalLevel)
3752 return RETURN_ERR;
3753 *SignalLevel=(radioIndex==0)?-19:-19;
3754
3755 return RETURN_OK;
3756}
3757
3758//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3759INT wifi_applyRadioSettings(INT radioIndex)
3760{
3761 return RETURN_OK;
3762}
3763
3764//Get the radio index assocated with this SSID entry
3765INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3766{
developer5b398df2022-11-17 20:39:48 +08003767 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003768 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003769 int max_radio_num = 0;
3770 wifi_getMaxRadioNumber(&max_radio_num);
3771 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003772 return RETURN_OK;
3773}
3774
3775//Device.WiFi.SSID.{i}.Enable
3776//Get SSID enable configuration parameters (not the SSID enable status)
3777INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3778{
3779 if (NULL == output_bool)
3780 return RETURN_ERR;
3781
developer06a01d92022-09-07 16:32:39 +08003782 return wifi_getApEnable(ssidIndex, output_bool);
3783}
3784
3785//Device.WiFi.SSID.{i}.Enable
3786//Set SSID enable configuration parameters
3787INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3788{
developer06a01d92022-09-07 16:32:39 +08003789 return wifi_setApEnable(ssidIndex, enable);
3790}
3791
3792//Device.WiFi.SSID.{i}.Status
3793//Get the SSID enable status
3794INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3795{
3796 char cmd[MAX_CMD_SIZE]={0};
3797 char buf[MAX_BUF_SIZE]={0};
3798 BOOL output_bool;
3799
3800 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3801 if (NULL == output_string)
3802 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003803
developer06a01d92022-09-07 16:32:39 +08003804 wifi_getApEnable(ssidIndex,&output_bool);
3805 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3806
3807 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3808 return RETURN_OK;
3809}
3810
3811// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3812INT wifi_getSSIDName(INT apIndex, CHAR *output)
3813{
3814 char config_file[MAX_BUF_SIZE] = {0};
3815
3816 if (NULL == output)
3817 return RETURN_ERR;
3818
3819 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3820 wifi_hostapdRead(config_file,"ssid",output,32);
3821
3822 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3823 return RETURN_OK;
3824}
3825
3826// Set a max 32 byte string and sets an internal variable to the SSID name
3827INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3828{
3829 char str[MAX_BUF_SIZE]={'\0'};
3830 char cmd[MAX_CMD_SIZE]={'\0'};
3831 struct params params;
3832 char config_file[MAX_BUF_SIZE] = {0};
3833
3834 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003835 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003836 return RETURN_ERR;
3837
3838 params.name = "ssid";
3839 params.value = ssid_string;
3840 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3841 wifi_hostapdWrite(config_file, &params, 1);
3842 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3844
3845 return RETURN_OK;
3846}
3847
3848//Get the BSSID
3849INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3850{
3851 char cmd[MAX_CMD_SIZE]="";
3852
3853 if (NULL == output_string)
3854 return RETURN_ERR;
3855
3856 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3857 {
developer1d57d002022-10-12 18:03:15 +08003858 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 +08003859 _syscmd(cmd, output_string, 64);
3860 return RETURN_OK;
3861 }
3862 strncpy(output_string, "\0", 1);
3863
3864 return RETURN_ERR;
3865}
3866
3867//Get the MAC address associated with this Wifi SSID
3868INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3869{
3870 wifi_getBaseBSSID(ssidIndex,output_string);
3871 return RETURN_OK;
3872}
3873
3874//Get the basic SSID traffic static info
3875//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3876//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3877INT wifi_applySSIDSettings(INT ssidIndex)
3878{
developerd946fd62022-12-08 18:03:28 +08003879 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003880 BOOL status = false;
3881 char cmd[MAX_CMD_SIZE] = {0};
3882 char buf[MAX_CMD_SIZE] = {0};
3883 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003884 int max_radio_num = 0;
3885 int radioIndex = 0;
3886
3887 wifi_getMaxRadioNumber(&max_radio_num);
3888
3889 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003890
3891 wifi_getApEnable(ssidIndex,&status);
3892 // Do not apply when ssid index is disabled
3893 if (status == false)
3894 return RETURN_OK;
3895
3896 /* Doing full remove and add for ssid Index
3897 * Not all hostapd options are supported with reload
3898 * for example macaddr_acl
3899 */
3900 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3901 return RETURN_ERR;
3902
3903 ret = wifi_setApEnable(ssidIndex,true);
3904
3905 /* Workaround for hostapd issue with multiple bss definitions
3906 * when first created interface will be removed
3907 * then all vaps other vaps on same phy are removed
3908 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003909 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003910 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003911 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003912 continue;
developer643b28f2023-04-04 10:26:01 +08003913 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003914 _syscmd(cmd, buf, sizeof(buf));
3915 if(*buf == '1')
3916 wifi_setApEnable(apIndex, true);
3917 }
3918
3919 return ret;
3920}
3921
developera3c68b92022-09-13 15:27:29 +08003922struct channels_noise {
3923 int channel;
3924 int noise;
3925};
3926
3927// Return noise array for each channel
3928int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3929{
developerd946fd62022-12-08 18:03:28 +08003930 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003931 FILE *f = NULL;
3932 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003933 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003934 size_t len = 0;
3935 ssize_t read = 0;
3936 int tmp = 0, arr_index = -1;
3937
developerac6f1142022-12-20 19:26:35 +08003938 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003939 return RETURN_ERR;
3940 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003941
3942 if ((f = popen(cmd, "r")) == NULL) {
3943 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3944 return RETURN_ERR;
3945 }
developer5550e242022-09-30 09:59:32 +08003946
3947 while(fgets(line, sizeof(line), f) != NULL) {
3948 if(arr_index < channels_num){
3949 sscanf(line, "%d", &tmp);
3950 if (tmp > 0) { // channel frequency, the first line must be frequency
3951 arr_index++;
3952 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3953 } else { // noise
3954 channels_noise_arr[arr_index].noise = tmp;
3955 }
3956 }else{
3957 break;
developera3c68b92022-09-13 15:27:29 +08003958 }
3959 }
developera3c68b92022-09-13 15:27:29 +08003960 pclose(f);
3961 return RETURN_OK;
3962}
3963
developer06a01d92022-09-07 16:32:39 +08003964//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3965//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3966INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3967{
developera3c68b92022-09-13 15:27:29 +08003968 int index = -1;
3969 wifi_neighbor_ap2_t *scan_array = NULL;
3970 char cmd[256]={0};
3971 char buf[128]={0};
3972 char file_name[32] = {0};
3973 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003974 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003975 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003976 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003977 int freq=0;
3978 FILE *f = NULL;
3979 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003980 int channels_num = 0;
3981 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003982 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003983 bool filter_enable = false;
3984 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003985 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003986
developer615510b2022-09-27 10:14:35 +08003987 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003988
developerac6f1142022-12-20 19:26:35 +08003989 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003990 return RETURN_ERR;
3991
developera3c68b92022-09-13 15:27:29 +08003992 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3993 f = fopen(file_name, "r");
3994 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08003995 fgets(buf, sizeof(file_name), f);
3996 if ((strncmp(buf, "0", 1)) != 0) {
3997 fgets(filter_SSID, sizeof(file_name), f);
3998 if (strlen(filter_SSID) != 0)
3999 filter_enable = true;
4000 }
developera3c68b92022-09-13 15:27:29 +08004001 fclose(f);
4002 }
4003
developer033b37b2022-10-18 11:27:46 +08004004 phyId = radio_index_to_phy(radioIndex);
4005 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08004006 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08004007 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004008
developer5550e242022-09-30 09:59:32 +08004009
developer06a01d92022-09-07 16:32:39 +08004010
developerd946fd62022-12-08 18:03:28 +08004011 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4012 // 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 +08004013 fprintf(stderr, "cmd: %s\n", cmd);
4014 if ((f = popen(cmd, "r")) == NULL) {
4015 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4016 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004017 }
developer5550e242022-09-30 09:59:32 +08004018
4019 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4020 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
4021
developer615510b2022-09-27 10:14:35 +08004022 ret = fgets(line, sizeof(line), f);
4023 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08004024 if(strstr(line, "BSS") != NULL) { // new neighbor info
4025 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
4026 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4027 // 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 +08004028
developera3c68b92022-09-13 15:27:29 +08004029 if (!filter_BSS) {
4030 index++;
4031 wifi_neighbor_ap2_t *tmp;
4032 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4033 if (tmp == NULL) { // no more memory to use
4034 index--;
4035 wifi_dbg_printf("%s: realloc failed\n", __func__);
4036 break;
4037 }
4038 scan_array = tmp;
4039 }
4040 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4041
4042 filter_BSS = false;
4043 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4044 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4045 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4046 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4047 } else if (strstr(line, "freq") != NULL) {
4048 sscanf(line," freq: %d", &freq);
4049 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4050
4051 if (freq >= 2412 && freq <= 2484) {
4052 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4053 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4054 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4055 }
4056 else if (freq >= 5160 && freq <= 5805) {
4057 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4058 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4059 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4060 }
4061
4062 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08004063 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08004064 for (int i = 0; i < channels_num; i++) {
4065 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4066 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4067 break;
4068 }
4069 }
4070 }
4071 } else if (strstr(line, "beacon interval") != NULL) {
4072 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4073 } else if (strstr(line, "signal") != NULL) {
4074 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4075 } else if (strstr(line,"SSID") != NULL) {
4076 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4077 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4078 filter_BSS = true;
4079 }
4080 } else if (strstr(line, "Supported rates") != NULL) {
4081 char SRate[80] = {0}, *tmp = NULL;
4082 memset(buf, 0, sizeof(buf));
4083 strcpy(SRate, line);
4084 tmp = strtok(SRate, ":");
4085 tmp = strtok(NULL, ":");
4086 strcpy(buf, tmp);
4087 memset(SRate, 0, sizeof(SRate));
4088
4089 tmp = strtok(buf, " \n");
4090 while (tmp != NULL) {
4091 strcat(SRate, tmp);
4092 if (SRate[strlen(SRate) - 1] == '*') {
4093 SRate[strlen(SRate) - 1] = '\0';
4094 }
4095 strcat(SRate, ",");
4096
4097 tmp = strtok(NULL, " \n");
4098 }
4099 SRate[strlen(SRate) - 1] = '\0';
4100 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4101 } else if (strstr(line, "DTIM") != NULL) {
4102 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4103 } else if (strstr(line, "VHT capabilities") != NULL) {
4104 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4105 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4106 } else if (strstr(line, "HT capabilities") != NULL) {
4107 strcat(scan_array[index].ap_SupportedStandards, ",n");
4108 strcpy(scan_array[index].ap_OperatingStandards, "n");
4109 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004110 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004111 sscanf(line," * channel width: %d", &vht_channel_width);
4112 if(vht_channel_width == 1) {
4113 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4114 } else {
4115 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4116 }
4117 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4118 continue;
4119 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004120 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004121 sscanf(line," * secondary channel offset: %s", &buf);
4122 if (!strcmp(buf, "above")) {
4123 //40Mhz +
4124 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4125 }
4126 else if (!strcmp(buf, "below")) {
4127 //40Mhz -
4128 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4129 } else {
4130 //20Mhz
4131 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4132 }
4133 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4134 continue;
4135 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004136 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4137 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4138 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004139 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4140 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004141 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004142 else
developer615510b2022-09-27 10:14:35 +08004143 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004144 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004145 if (strstr(line, "HE80/5GHz") != NULL) {
4146 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4147 ret = fgets(line, sizeof(line), f);
4148 } else
4149 continue;
developera3c68b92022-09-13 15:27:29 +08004150 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004151 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004152 }
developer615510b2022-09-27 10:14:35 +08004153 continue;
developera3c68b92022-09-13 15:27:29 +08004154 } else if (strstr(line, "WPA") != NULL) {
4155 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4156 } else if (strstr(line, "RSN") != NULL) {
4157 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4158 } else if (strstr(line, "Group cipher") != NULL) {
4159 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4160 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4161 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4162 }
4163 }
developer615510b2022-09-27 10:14:35 +08004164 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004165 }
4166
4167 if (!filter_BSS) {
4168 *output_array_size = index + 1;
4169 } else {
4170 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4171 *output_array_size = index;
4172 }
4173 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004174 pclose(f);
developer5550e242022-09-30 09:59:32 +08004175 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004176 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004177 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004178}
4179
4180//>> Deprecated: used for old RDKB code.
4181INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4182{
4183 INT status = RETURN_ERR;
4184
4185 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4186 output_struct->wifi_PLCPErrorCount = 0;
4187 output_struct->wifi_FCSErrorCount = 0;
4188 output_struct->wifi_InvalidMACCount = 0;
4189 output_struct->wifi_PacketsOtherReceived = 0;
4190 output_struct->wifi_Noise = 0;
4191 status = RETURN_OK;
4192 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4193 return status;
4194}
4195
4196INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4197{
developerd946fd62022-12-08 18:03:28 +08004198 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004199 char cmd[128] = {0};
4200 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004201 char *pos = NULL;
4202
4203 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4204 if (NULL == output_struct)
4205 return RETURN_ERR;
4206
developerac6f1142022-12-20 19:26:35 +08004207 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004208 return RETURN_ERR;
4209
developer06a01d92022-09-07 16:32:39 +08004210 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4211
developerd946fd62022-12-08 18:03:28 +08004212 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004213 _syscmd(cmd, buf, sizeof(buf));
4214
4215 pos = buf;
4216 if ((pos = strstr(pos, "RX packets:")) == NULL)
4217 return RETURN_ERR;
4218 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4219
4220 if ((pos = strstr(pos, "TX packets:")) == NULL)
4221 return RETURN_ERR;
4222 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4223
4224 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4225 return RETURN_ERR;
4226 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4227
4228 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4229 return RETURN_ERR;
4230 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4231
developerd946fd62022-12-08 18:03:28 +08004232 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004233 _syscmd(cmd, buf, sizeof(buf));
4234 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4235
4236#if 0
4237 //TODO: need to revisit below implementation
4238 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4239 char interface_name[MAX_BUF_SIZE] = {0};
4240 char interface_status[MAX_BUF_SIZE] = {0};
4241 char Value[MAX_BUF_SIZE] = {0};
4242 char buf[MAX_CMD_SIZE] = {0};
4243 char cmd[MAX_CMD_SIZE] = {0};
4244 FILE *fp = NULL;
4245
4246 if (NULL == output_struct) {
4247 return RETURN_ERR;
4248 }
4249
4250 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4251
4252 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4253 {
4254 if(apIndex == 0) //private_wifi for 2.4G
4255 {
developerac6f1142022-12-20 19:26:35 +08004256 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004257 }
4258 else if(apIndex == 1) //private_wifi for 5G
4259 {
developerac6f1142022-12-20 19:26:35 +08004260 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004261 }
4262 else if(apIndex == 4) //public_wifi for 2.4G
4263 {
4264 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4265 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4266 {
4267 return RETURN_ERR;
4268 }
4269 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004270 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004271 else//tenda
developerac6f1142022-12-20 19:26:35 +08004272 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004273 }
4274 else if(apIndex == 5) //public_wifi for 5G
4275 {
developerac6f1142022-12-20 19:26:35 +08004276 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004277 }
4278
4279 GetIfacestatus(interface_name, interface_status);
4280
4281 if(0 != strcmp(interface_status, "1"))
4282 return RETURN_ERR;
4283
4284 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4285 system(cmd);
4286
4287 fp = fopen("/tmp/SSID_Stats.txt", "r");
4288 if(fp == NULL)
4289 {
4290 printf("/tmp/SSID_Stats.txt not exists \n");
4291 return RETURN_ERR;
4292 }
4293 fclose(fp);
4294
4295 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4296 File_Reading(buf, Value);
4297 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4298
4299 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4300 File_Reading(buf, Value);
4301 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4302
4303 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4304 File_Reading(buf, Value);
4305 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4306
4307 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4308 File_Reading(buf, Value);
4309 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4310
4311 /* There is no specific parameter from caller to associate the value wifi_Associations */
4312 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4313 //_syscmd(cmd, buf, sizeof(buf));
4314 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4315 }
4316#endif
4317 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4318 return RETURN_OK;
4319}
4320
4321INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4322{
4323 char interface_name[MAX_BUF_SIZE] = {0};
4324 char interface_status[MAX_BUF_SIZE] = {0};
4325 char Value[MAX_BUF_SIZE] = {0};
4326 char buf[MAX_CMD_SIZE] = {0};
4327 char cmd[MAX_CMD_SIZE] = {0};
4328 FILE *fp = NULL;
4329
4330 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4331 if (NULL == output_struct)
4332 return RETURN_ERR;
4333
4334 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4335
developerac6f1142022-12-20 19:26:35 +08004336 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004337 return RETURN_ERR;
4338 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004339
developerd946fd62022-12-08 18:03:28 +08004340 if(0 != strcmp(interface_status, "1"))
4341 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004342
developerd946fd62022-12-08 18:03:28 +08004343 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4344 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004345
developerd946fd62022-12-08 18:03:28 +08004346 fp = fopen("/tmp/SSID_Stats.txt", "r");
4347 if(fp == NULL)
4348 {
4349 printf("/tmp/SSID_Stats.txt not exists \n");
4350 return RETURN_ERR;
4351 }
4352 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004353
developerd946fd62022-12-08 18:03:28 +08004354 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4355 File_Reading(buf, Value);
4356 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004357
developerd946fd62022-12-08 18:03:28 +08004358 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4359 File_Reading(buf, Value);
4360 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004361
developerd946fd62022-12-08 18:03:28 +08004362 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4363 File_Reading(buf, Value);
4364 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004365
developerd946fd62022-12-08 18:03:28 +08004366 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4367 File_Reading(buf, Value);
4368 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004369
4370 output_struct->wifi_UnicastPacketsSent = 0;
4371 output_struct->wifi_UnicastPacketsReceived = 0;
4372 output_struct->wifi_MulticastPacketsSent = 0;
4373 output_struct->wifi_MulticastPacketsReceived = 0;
4374 output_struct->wifi_BroadcastPacketsSent = 0;
4375 output_struct->wifi_BroadcastPacketsRecevied = 0;
4376 output_struct->wifi_UnknownPacketsReceived = 0;
4377
4378 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4379 return RETURN_OK;
4380}
4381
4382INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4383{
4384 INT status = RETURN_ERR;
4385
4386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4387 //Below values should get updated from hal
4388 output_struct->wifi_RetransCount=0;
4389 output_struct->wifi_FailedRetransCount=0;
4390 output_struct->wifi_RetryCount=0;
4391 output_struct->wifi_MultipleRetryCount=0;
4392 output_struct->wifi_ACKFailureCount=0;
4393 output_struct->wifi_AggregatedPacketCount=0;
4394
4395 status = RETURN_OK;
4396 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4397
4398 return status;
4399}
4400
4401INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4402{
4403 INT status = RETURN_ERR;
4404 UINT index;
4405 wifi_neighbor_ap_t *pt=NULL;
4406
4407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4408 *output_array_size=2;
4409 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4410 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4411 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4412 strcpy(pt->ap_Radio,"");
4413 strcpy(pt->ap_SSID,"");
4414 strcpy(pt->ap_BSSID,"");
4415 strcpy(pt->ap_Mode,"");
4416 pt->ap_Channel=1;
4417 pt->ap_SignalStrength=0;
4418 strcpy(pt->ap_SecurityModeEnabled,"");
4419 strcpy(pt->ap_EncryptionMode,"");
4420 strcpy(pt->ap_OperatingFrequencyBand,"");
4421 strcpy(pt->ap_SupportedStandards,"");
4422 strcpy(pt->ap_OperatingStandards,"");
4423 strcpy(pt->ap_OperatingChannelBandwidth,"");
4424 pt->ap_BeaconPeriod=1;
4425 pt->ap_Noise=0;
4426 strcpy(pt->ap_BasicDataTransferRates,"");
4427 strcpy(pt->ap_SupportedDataTransferRates,"");
4428 pt->ap_DTIMPeriod=1;
4429 pt->ap_ChannelUtilization = 1;
4430 }
4431
4432 status = RETURN_OK;
4433 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4434
4435 return status;
4436}
4437
4438//----------------- AP HAL -------------------------------
4439
4440//>> Deprecated: used for old RDKB code.
4441INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4442{
4443 if (NULL == output_ulong || NULL == output_struct)
4444 return RETURN_ERR;
4445 *output_ulong = 0;
4446 *output_struct = NULL;
4447 return RETURN_OK;
4448}
4449
4450#ifdef HAL_NETLINK_IMPL
4451static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4452 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4453 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4454 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4455 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4456 char mac_addr[20];
4457 static int count=0;
4458 int rate=0;
4459
4460 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4461
4462 nla_parse(tb,
4463 NL80211_ATTR_MAX,
4464 genlmsg_attrdata(gnlh, 0),
4465 genlmsg_attrlen(gnlh, 0),
4466 NULL);
4467
4468 if(!tb[NL80211_ATTR_STA_INFO]) {
4469 fprintf(stderr, "sta stats missing!\n");
4470 return NL_SKIP;
4471 }
4472
4473
4474 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4475 fprintf(stderr, "failed to parse nested attributes!\n");
4476 return NL_SKIP;
4477 }
4478
4479 //devIndex starts from 1
4480 if( ++count == out->wifi_devIndex )
4481 {
4482 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4483 //Getting the mac addrress
4484 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4485
4486 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4487 fprintf(stderr, "failed to parse nested rate attributes!");
4488 return NL_SKIP;
4489 }
4490
4491 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4492 if(rinfo[NL80211_RATE_INFO_BITRATE])
4493 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4494 out->wifi_devTxRate = rate/10;
4495 }
4496
4497 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4498 fprintf(stderr, "failed to parse nested rate attributes!");
4499 return NL_SKIP;
4500 }
4501
4502 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4503 if(rinfo[NL80211_RATE_INFO_BITRATE])
4504 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4505 out->wifi_devRxRate = rate/10;
4506 }
4507 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4508 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4509
4510 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4511 count = 0; //starts the count for next cycle
4512 return NL_STOP;
4513 }
4514
4515 return NL_SKIP;
4516
4517}
4518#endif
4519
4520INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4521{
4522#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004523 Netlink nl = {0};
4524 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004525 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004526
developer30423732022-12-01 16:17:49 +08004527 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004528 info.wifi_devIndex = devIndex;
4529
developerac6f1142022-12-20 19:26:35 +08004530 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004531 return RETURN_ERR;
4532
4533 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004534
4535 nl.id = initSock80211(&nl);
4536
4537 if (nl.id < 0) {
4538 fprintf(stderr, "Error initializing netlink \n");
4539 return -1;
4540 }
4541
4542 struct nl_msg* msg = nlmsg_alloc();
4543
4544 if (!msg) {
4545 fprintf(stderr, "Failed to allocate netlink message.\n");
4546 nlfree(&nl);
4547 return -2;
4548 }
4549
4550 genlmsg_put(msg,
4551 NL_AUTO_PORT,
4552 NL_AUTO_SEQ,
4553 nl.id,
4554 0,
4555 NLM_F_DUMP,
4556 NL80211_CMD_GET_STATION,
4557 0);
4558
4559 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4560 nl_send_auto(nl.socket, msg);
4561 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4562 nl_recvmsgs(nl.socket, nl.cb);
4563 nlmsg_free(msg);
4564 nlfree(&nl);
4565
4566 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4567 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4568 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4569 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4570 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4571 return RETURN_OK;
4572#else
4573 //iw utility to retrieve station information
4574#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4575#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4576#define MACFILE "/tmp/wifi_AssoMac.txt"
4577#define TXRATEFILE "/tmp/wifi_txrate.txt"
4578#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4579 FILE *file = NULL;
4580 char if_name[10] = {'\0'};
4581 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004582 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004583 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004584 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004585
developerac6f1142022-12-20 19:26:35 +08004586 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004587 return RETURN_ERR;
4588
4589 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004590
4591 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4592 file = popen(pipeCmd, "r");
4593
4594 if(file == NULL)
4595 return RETURN_ERR; //popen failed
4596
4597 fgets(line, sizeof line, file);
4598 device = atoi(line);
4599 pclose(file);
4600
4601 if(device == 0)
4602 return RETURN_ERR; //No devices are connected
4603
4604 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4605 system(pipeCmd);
4606
4607 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4608
4609 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4610
4611 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4612
4613 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4614
4615 //devIndex starts from 1, ++count
4616 if((file = fopen(SIGNALFILE, "r")) != NULL )
4617 {
4618 for(count =0;fgets(line, sizeof line, file) != NULL;)
4619 {
4620 if (++count == devIndex)
4621 {
4622 output_struct->wifi_devSignalStrength = atoi(line);
4623 break;
4624 }
4625 }
4626 fclose(file);
4627 }
4628 else
4629 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4630
4631 if((file = fopen(MACFILE, "r")) != NULL )
4632 {
4633 for(count =0;fgets(line, sizeof line, file) != NULL;)
4634 {
4635 if (++count == devIndex)
4636 {
4637 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]);
4638 break;
4639 }
4640 }
4641 fclose(file);
4642 }
4643 else
4644 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4645
4646 if((file = fopen(TXRATEFILE, "r")) != NULL )
4647 {
4648 for(count =0;fgets(line, sizeof line, file) != NULL;)
4649 {
4650 if (++count == devIndex)
4651 {
4652 output_struct->wifi_devTxRate = atoi(line);
4653 break;
4654 }
4655 }
4656 fclose(file);
4657 }
4658 else
4659 fprintf(stderr,"fopen wifi_txrate.txt failed");
4660
4661 if((file = fopen(RXRATEFILE, "r")) != NULL)
4662 {
4663 for(count =0;fgets(line, sizeof line, file) != NULL;)
4664 {
4665 if (++count == devIndex)
4666 {
4667 output_struct->wifi_devRxRate = atoi(line);
4668 break;
4669 }
4670 }
4671 fclose(file);
4672 }
4673 else
4674 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4675
4676 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4677
4678 return RETURN_OK;
4679#endif
4680}
4681
4682INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4683{
4684 if (NULL == device)
4685 return RETURN_ERR;
4686 return RETURN_OK;
4687}
4688//<<
4689
4690
4691//--------------wifi_ap_hal-----------------------------
4692//enables CTS protection for the radio used by this AP
4693INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4694{
4695 //save config and Apply instantly
4696 return RETURN_ERR;
4697}
4698
4699// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4700INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4701{
developer463d39a2022-09-13 15:32:51 +08004702 char config_file[64] = {'\0'};
4703 char buf[64] = {'\0'};
4704 struct params list;
4705
4706 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4707 list.name = "ht_coex";
4708 snprintf(buf, sizeof(buf), "%d", enable);
4709 list.value = buf;
4710
4711 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4712 wifi_hostapdWrite(config_file, &list, 1);
4713 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4714
4715 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4716
4717 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004718}
4719
4720//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4721INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4722{
developerea4bcce2022-09-13 15:26:13 +08004723 char config_file[MAX_BUF_SIZE] = {'\0'};
4724 char buf[MAX_BUF_SIZE] = {'\0'};
4725 struct params list;
4726
4727 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4728 if (threshold < 256 || threshold > 2346 )
4729 return RETURN_ERR;
4730 list.name = "fragm_threshold";
4731 snprintf(buf, sizeof(buf), "%d", threshold);
4732 list.value = buf;
4733
4734 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4735 wifi_hostapdWrite(config_file, &list, 1);
4736 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004737
developerea4bcce2022-09-13 15:26:13 +08004738 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004739
4740 return RETURN_OK;
4741}
4742
4743// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4744INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4745{
developer51a927d2022-09-13 15:42:22 +08004746 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004747 char cmd[512] = {'\0'};
4748 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004749 char stbc_config[16] = {'\0'};
4750 wifi_band band;
4751 int iterator = 0;
4752 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004753 int ant_count = 0;
4754 int ant_bitmap = 0;
4755 struct params list;
developer51a927d2022-09-13 15:42:22 +08004756
4757 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4758
4759 band = wifi_index_to_band(radioIndex);
4760 if (band == band_invalid)
4761 return RETURN_ERR;
4762
4763 if (band == band_2_4)
4764 iterator = 1;
4765 else if (band == band_5)
4766 iterator = 2;
4767 else
4768 return RETURN_OK;
4769
developer110b8a32022-12-26 15:56:44 +08004770 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4771 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4772 ant_count += ant_bitmap & 1;
4773
4774 if (ant_count == 1 && STBC_Enable == TRUE) {
4775 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4776 return RETURN_OK;
4777 }
4778
developer51a927d2022-09-13 15:42:22 +08004779 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4780
4781 // set ht and vht config
4782 for (int i = 0; i < iterator; i++) {
4783 memset(stbc_config, 0, sizeof(stbc_config));
4784 memset(cmd, 0, sizeof(cmd));
4785 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004786 list.name = (i == 0)?"ht_capab":"vht_capab";
4787 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004788 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4789 _syscmd(cmd, buf, sizeof(buf));
4790 if (strlen(buf) != 0)
4791 current_stbc = TRUE;
4792 if (current_stbc == STBC_Enable)
4793 continue;
4794
4795 if (STBC_Enable == TRUE) {
4796 // Append the STBC flags in capab config
4797 memset(cmd, 0, sizeof(cmd));
4798 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004799 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004800 else
developer6372c2b2022-10-27 17:39:51 +08004801 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 +08004802 _syscmd(cmd, buf, sizeof(buf));
4803 } else if (STBC_Enable == FALSE) {
4804 // Remove the STBC flags and remain other flags in capab
4805 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004806 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004807 _syscmd(cmd, buf, sizeof(buf));
4808 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004809 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004810 _syscmd(cmd, buf, sizeof(buf));
4811 }
developer110b8a32022-12-26 15:56:44 +08004812 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4813 list.value = buf;
4814 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004815 }
4816
4817 wifi_reloadAp(radioIndex);
4818
4819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4820 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004821}
4822
4823// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4824INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4825{
developerfe7aefc2022-12-23 17:13:37 +08004826 char cmd[128] = {0};
4827 char buf[128] = {0};
4828 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004829
4830 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4831
4832 if(output_bool == NULL)
4833 return RETURN_ERR;
4834
developerfe7aefc2022-12-23 17:13:37 +08004835 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4836 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004837
developerfe7aefc2022-12-23 17:13:37 +08004838 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4839 _syscmd(cmd, buf, sizeof(buf));
4840
4841 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004842 *output_bool = TRUE;
4843 else
4844 *output_bool = FALSE;
4845
4846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4847 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004848}
4849
4850// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4851INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4852{
developerfe7aefc2022-12-23 17:13:37 +08004853 char config_file[128] = {0};
4854 struct params list = {0};
4855 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004856
4857 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4858
developerfe7aefc2022-12-23 17:13:37 +08004859 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004860 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004861
developerfe7aefc2022-12-23 17:13:37 +08004862 if (amsduEnable == enable)
4863 return RETURN_OK;
4864
4865 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4866 list.name = "amsdu";
4867 list.value = amsduEnable? "1":"0";
4868 wifi_hostapdWrite(config_file, &list, 1);
4869 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4870 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004871
4872 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4873 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004874}
4875
4876//P2 // outputs the number of Tx streams
4877INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4878{
developer2de97692022-09-26 14:00:03 +08004879 char buf[8] = {0};
4880 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004881 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004882
4883 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4884
developer033b37b2022-10-18 11:27:46 +08004885 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004886 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004887 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004888
developer110b8a32022-12-26 15:56:44 +08004889 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004890
4891 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4892
4893 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004894}
4895
developer110b8a32022-12-26 15:56:44 +08004896INT fitChainMask(INT radioIndex, int antcount)
4897{
4898 char buf[128] = {0};
4899 char cmd[128] = {0};
4900 char config_file[64] = {0};
4901 wifi_band band;
4902 struct params list[2] = {0};
4903
4904 band = wifi_index_to_band(radioIndex);
4905 if (band == band_invalid)
4906 return RETURN_ERR;
4907
4908 list[0].name = "he_mu_beamformer";
4909 list[1].name = "he_su_beamformer";
4910
4911 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4912 if (antcount == 1) {
4913 // remove config about multiple antennas
4914 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4915 _syscmd(cmd, buf, sizeof(buf));
4916
4917 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4918 _syscmd(cmd, buf, sizeof(buf));
4919
4920 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4921 _syscmd(cmd, buf, sizeof(buf));
4922
4923 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4924 _syscmd(cmd, buf, sizeof(buf));
4925
4926 list[0].value = "0";
4927 list[1].value = "0";
4928 } else {
4929 // 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.
4930 if (band == band_2_4 || band == band_5) {
4931 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4932 _syscmd(cmd, buf, sizeof(buf));
4933 if (strlen(buf) > 0) {
4934 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4935 _syscmd(cmd, buf, sizeof(buf));
4936 }
4937 }
4938 if (band == band_5) {
4939 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4940 _syscmd(cmd, buf, sizeof(buf));
4941 if (strlen(buf) > 0) {
4942 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4943 _syscmd(cmd, buf, sizeof(buf));
4944 }
4945 }
4946
4947 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4948 _syscmd(cmd, buf, sizeof(buf));
4949 if (strlen(buf) == 0) {
4950 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4951 _syscmd(cmd, buf, sizeof(buf));
4952 }
4953
4954 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4955 _syscmd(cmd, buf, sizeof(buf));
4956 if (strlen(buf) == 0) {
4957 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4958 _syscmd(cmd, buf, sizeof(buf));
4959 }
4960
4961 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4962 _syscmd(cmd, buf, sizeof(buf));
4963 if (strlen(buf) == 0) {
4964 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4965 } else {
4966 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4967 }
4968 _syscmd(cmd, buf, sizeof(buf));
4969
4970 list[0].value = "1";
4971 list[1].value = "1";
4972 }
4973 wifi_hostapdWrite(config_file, list, 2);
4974}
4975
developer06a01d92022-09-07 16:32:39 +08004976//P2 // sets the number of Tx streams to an enviornment variable
4977INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4978{
developer2de97692022-09-26 14:00:03 +08004979 char cmd[128] = {0};
4980 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004981 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08004982 int cur_mask = 0;
4983 int antcount = 0;
4984 wifi_band band;
developer2de97692022-09-26 14:00:03 +08004985
4986 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4987
developer110b8a32022-12-26 15:56:44 +08004988 if (numStreams <= 0) {
4989 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08004990 return RETURN_ERR;
4991 }
developer110b8a32022-12-26 15:56:44 +08004992
4993 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
4994 if (cur_mask == numStreams)
4995 return RETURN_OK;
4996
developer2de97692022-09-26 14:00:03 +08004997 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004998
4999 phyId = radio_index_to_phy(radioIndex);
5000 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08005001 _syscmd(cmd, buf, sizeof(buf));
5002
5003 if (strlen(buf) > 0) {
5004 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5005 return RETURN_ERR;
5006 }
developer2de97692022-09-26 14:00:03 +08005007
developer110b8a32022-12-26 15:56:44 +08005008 // if chain mask changed, we need to make the hostapd config valid.
5009 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5010 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08005011 }
developer110b8a32022-12-26 15:56:44 +08005012 fitChainMask(radioIndex, antcount);
5013
5014 wifi_setRadioEnable(radioIndex, TRUE);
5015
developer2de97692022-09-26 14:00:03 +08005016 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5017 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005018}
5019
5020//P2 // outputs the number of Rx streams
5021INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5022{
developer110b8a32022-12-26 15:56:44 +08005023 char buf[8] = {0};
5024 char cmd[128] = {0};
5025 int phyId = 0;
5026
developer2de97692022-09-26 14:00:03 +08005027 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005028
5029 phyId = radio_index_to_phy(radioIndex);
5030 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5031 _syscmd(cmd, buf, sizeof(buf));
5032
5033 *output_int = (INT)strtol(buf, NULL, 16);
5034
developer2de97692022-09-26 14:00:03 +08005035 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005036
developer06a01d92022-09-07 16:32:39 +08005037 return RETURN_OK;
5038}
5039
5040//P2 // sets the number of Rx streams to an enviornment variable
5041INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5042{
developer2de97692022-09-26 14:00:03 +08005043 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5044 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5045 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5046 return RETURN_ERR;
5047 }
5048 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005049 return RETURN_ERR;
5050}
5051
5052//Get radio RDG enable setting
5053INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5054{
5055 if (NULL == output_bool)
5056 return RETURN_ERR;
5057 *output_bool = TRUE;
5058 return RETURN_OK;
5059}
5060
5061//Get radio RDG enable setting
5062INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5063{
5064 if (NULL == output_bool)
5065 return RETURN_ERR;
5066 *output_bool = TRUE;
5067 return RETURN_OK;
5068}
5069
5070//Set radio RDG enable setting
5071INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5072{
5073 return RETURN_ERR;
5074}
5075
5076//Get radio ADDBA enable setting
5077INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5078{
5079 if (NULL == output_bool)
5080 return RETURN_ERR;
5081 *output_bool = TRUE;
5082 return RETURN_OK;
5083}
5084
5085//Set radio ADDBA enable setting
5086INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5087{
5088 return RETURN_ERR;
5089}
5090
5091//Get radio auto block ack enable setting
5092INT wifi_getRadioAutoBlockAckEnable(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 auto block ack enable setting
5101INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5102{
5103 return RETURN_ERR;
5104}
5105
5106//Get radio 11n pure mode enable support
5107INT wifi_getRadio11nGreenfieldSupported(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//Get radio 11n pure mode enable setting
5116INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5117{
5118 if (NULL == output_bool)
5119 return RETURN_ERR;
5120 *output_bool = TRUE;
5121 return RETURN_OK;
5122}
5123
5124//Set radio 11n pure mode enable setting
5125INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5126{
5127 return RETURN_ERR;
5128}
5129
5130//Get radio IGMP snooping enable setting
5131INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5132{
developerd946fd62022-12-08 18:03:28 +08005133 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005134 char cmd[128]={0};
5135 char buf[4]={0};
5136 bool bridge = FALSE, mac80211 = FALSE;
5137 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5138
5139 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005140 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005141
5142 *output_bool = FALSE;
5143
5144 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5145 _syscmd(cmd, buf, sizeof(buf));
5146 if (strncmp(buf, "1", 1) == 0)
5147 bridge = TRUE;
5148
developerac6f1142022-12-20 19:26:35 +08005149 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005150 return RETURN_ERR;
5151 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 +08005152 _syscmd(cmd, buf, sizeof(buf));
5153 if (strncmp(buf, "1", 1) == 0)
5154 mac80211 = TRUE;
5155
5156 if (bridge && mac80211)
5157 *output_bool = TRUE;
5158
5159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005160 return RETURN_OK;
5161}
5162
5163//Set radio IGMP snooping enable setting
5164INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5165{
developerd946fd62022-12-08 18:03:28 +08005166 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005167 char cmd[128]={0};
5168 char buf[4]={0};
developer894affa2023-05-10 18:13:19 +08005169 int max_num_radios = 0;
5170 int apIndex = 0;
developer81bf2ed2022-09-13 15:31:14 +08005171 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5172
5173 // bridge
developerfb09ba62023-06-09 17:03:21 +08005174 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
developer81bf2ed2022-09-13 15:31:14 +08005175 _syscmd(cmd, buf, sizeof(buf));
5176
developer804c64f2022-10-19 13:54:40 +08005177 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005178 // mac80211
developer894affa2023-05-10 18:13:19 +08005179 for (int i = 0; i < MAX_NUM_VAP_PER_RADIO; i++) {
5180 apIndex = radioIndex + i*max_num_radios;
5181 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5182 continue;
developerfb09ba62023-06-09 17:03:21 +08005183 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 +08005184 _syscmd(cmd, buf, sizeof(buf));
5185 }
5186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5187 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005188}
5189
5190//Get the Reset count of radio
5191INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5192{
5193 if (NULL == output_int)
5194 return RETURN_ERR;
5195 *output_int = (radioIndex==0)? 1: 3;
5196
5197 return RETURN_OK;
5198}
5199
5200
5201//---------------------------------------------------------------------------------------------------
5202//
5203// Additional Wifi AP level APIs used for Access Point devices
5204//
5205//---------------------------------------------------------------------------------------------------
5206
5207// creates a new ap and pushes these parameters to the hardware
5208INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5209{
developer7930d352022-12-21 17:55:42 +08005210 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005211 return RETURN_OK;
5212}
5213
5214// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5215INT wifi_deleteAp(INT apIndex)
5216{
developerd946fd62022-12-08 18:03:28 +08005217 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005218 char buf[128] = {0};
5219 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005220
developerac6f1142022-12-20 19:26:35 +08005221 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005222 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005223
developer89df4502023-02-16 20:45:02 +08005224 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5225 return RETURN_ERR;
5226
developer7930d352022-12-21 17:55:42 +08005227 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005228 _syscmd(cmd, buf, sizeof(buf));
5229
5230 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005231 return RETURN_OK;
5232}
5233
5234// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5235INT wifi_getApName(INT apIndex, CHAR *output_string)
5236{
developerd946fd62022-12-08 18:03:28 +08005237 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005238 if(NULL == output_string)
5239 return RETURN_ERR;
5240
developerac6f1142022-12-20 19:26:35 +08005241 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005242 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005243 else
5244 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005245 return RETURN_OK;
5246}
5247
5248// Outputs the index number in that corresponds to the SSID string
5249INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5250{
developerd946fd62022-12-08 18:03:28 +08005251 char cmd [128] = {0};
5252 char buf[32] = {0};
5253 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005254 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005255
developerd946fd62022-12-08 18:03:28 +08005256 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5257 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005258
developerac6f1142022-12-20 19:26:35 +08005259 if (strlen(buf) != 0) {
5260 apIndex_str = strtok(buf, "\n");
5261 *output_int = strtoul(apIndex_str, NULL, 10);
5262 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005263 }
developer67b8ee92022-12-20 10:48:43 +08005264
5265 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5266 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5267 if (apIndex_str) {
5268 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5269 return RETURN_OK;
5270 }
developerd946fd62022-12-08 18:03:28 +08005271 *output_int = -1;
5272 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005273}
5274
5275INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5276{
5277 return wifi_getIndexFromName(inputSsidString, output_int);
5278}
5279
5280// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5281INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5282{
5283 char buf[MAX_BUF_SIZE] = {0};
5284 char cmd[MAX_CMD_SIZE] = {0};
5285 char config_file[MAX_BUF_SIZE] = {0};
5286
5287 if(NULL == output_string)
5288 return RETURN_ERR;
5289
5290 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5291 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5292 if((strcmp(buf,"3")==0))
5293 snprintf(output_string, 32, "WPAand11i");
5294 else if((strcmp(buf,"2")==0))
5295 snprintf(output_string, 32, "11i");
5296 else if((strcmp(buf,"1")==0))
5297 snprintf(output_string, 32, "WPA");
5298 else
5299 snprintf(output_string, 32, "None");
5300
5301 return RETURN_OK;
5302}
5303
5304// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5305INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5306{
5307 char config_file[MAX_BUF_SIZE] = {0};
5308 struct params list;
5309
5310 if (NULL == beaconTypeString)
5311 return RETURN_ERR;
5312 list.name = "wpa";
5313 list.value = "0";
5314
5315 if((strcmp(beaconTypeString,"WPAand11i")==0))
5316 list.value="3";
5317 else if((strcmp(beaconTypeString,"11i")==0))
5318 list.value="2";
5319 else if((strcmp(beaconTypeString,"WPA")==0))
5320 list.value="1";
5321
5322 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5323 wifi_hostapdWrite(config_file, &list, 1);
5324 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5325 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5326 return RETURN_OK;
5327}
5328
5329// sets the beacon interval on the hardware for this AP
5330INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5331{
developer5f222492022-09-13 15:21:52 +08005332 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5333 struct params params={'\0'};
5334 char buf[MAX_BUF_SIZE] = {'\0'};
5335 char config_file[MAX_BUF_SIZE] = {'\0'};
5336
5337 params.name = "beacon_int";
5338 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5339 params.value = buf;
5340
5341 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5342 wifi_hostapdWrite(config_file, &params, 1);
5343
5344 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5345 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5346 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005347}
5348
5349INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5350{
developer5b398df2022-11-17 20:39:48 +08005351 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5352 return RETURN_ERR;
5353 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005354}
5355
5356// Get the packet size threshold supported.
5357INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5358{
5359 //save config and apply instantly
5360 if (NULL == output_bool)
5361 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005362 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005363 return RETURN_OK;
5364}
5365
5366// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5367INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5368{
developer514406b2022-12-05 17:20:21 +08005369 char buf[16] = {0};
5370 char config_file[128] = {0};
5371 struct params param = {0};
5372
5373 if (threshold > 65535) {
5374 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5375 return RETURN_ERR;
5376 }
developer06a01d92022-09-07 16:32:39 +08005377
developer23e71282023-01-18 10:25:19 +08005378 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005379 snprintf(buf, sizeof(buf), "%u", threshold);
5380 param.name = "rts_threshold";
5381 param.value = buf;
5382 wifi_hostapdWrite(config_file, &param, 1);
5383 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5384 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005385
5386 return RETURN_OK;
5387}
5388
5389// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5390INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5391{
5392 if (NULL == output_string)
5393 return RETURN_ERR;
5394 snprintf(output_string, 32, "TKIPandAESEncryption");
5395 return RETURN_OK;
5396
5397}
5398
5399// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5400INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5401{
5402 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005403 char *param_name = NULL;
5404 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005405
5406 if(NULL == output_string)
5407 return RETURN_ERR;
5408
5409 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5410 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5411
5412 if(strcmp(buf,"0")==0)
5413 {
5414 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5415 snprintf(output_string, 32, "None");
5416 return RETURN_OK;
5417 }
5418 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5419 param_name = "rsn_pairwise";
5420 else if((strcmp(buf,"1")==0))
5421 param_name = "wpa_pairwise";
5422 else
5423 return RETURN_ERR;
5424 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005425 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005426 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5427 param_name = "wpa_pairwise";
5428 memset(output_string, '\0', 32);
5429 wifi_hostapdRead(config_file, param_name, output_string, 32);
5430 }
developer06a01d92022-09-07 16:32:39 +08005431 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5432
developer72ec5572023-01-05 16:27:13 +08005433 if(strcmp(output_string,"TKIP CCMP") == 0)
5434 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5435 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005436 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5437 else if(strcmp(output_string,"CCMP") == 0)
5438 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005439
5440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5441 return RETURN_OK;
5442}
5443
5444// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5445INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5446{
5447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5448 struct params params={'\0'};
5449 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005450 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005451
5452 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005453 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005454
5455 if(strcmp(encMode, "TKIPEncryption") == 0)
5456 params.value = "TKIP";
5457 else if(strcmp(encMode,"AESEncryption") == 0)
5458 params.value = "CCMP";
5459 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5460 params.value = "TKIP CCMP";
5461
5462 if((strcmp(output_string,"WPAand11i")==0))
5463 {
5464 params.name = "wpa_pairwise";
5465 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5466 wifi_hostapdWrite(config_file, &params, 1);
5467 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5468
developer30423732022-12-01 16:17:49 +08005469 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005470 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5471 wifi_hostapdWrite(config_file, &params, 1);
5472 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5473
5474 return RETURN_OK;
5475 }
5476 else if((strcmp(output_string,"11i")==0))
5477 {
5478 params.name = "rsn_pairwise";
5479 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5480 wifi_hostapdWrite(config_file, &params, 1);
5481 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5482 return RETURN_OK;
5483 }
5484 else if((strcmp(output_string,"WPA")==0))
5485 {
5486 params.name = "wpa_pairwise";
5487 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5488 wifi_hostapdWrite(config_file, &params, 1);
5489 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5490 return RETURN_OK;
5491 }
5492
5493 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5494 return RETURN_OK;
5495}
5496
5497// deletes internal security varable settings for this ap
5498INT wifi_removeApSecVaribles(INT apIndex)
5499{
5500 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005501 //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 +08005502 //_syscmd(cmd, buf, sizeof(buf));
5503
developerd946fd62022-12-08 18:03:28 +08005504 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005505 //_syscmd(cmd, buf, sizeof(buf));
5506 return RETURN_ERR;
5507}
5508
5509// changes the hardware settings to disable encryption on this ap
5510INT wifi_disableApEncryption(INT apIndex)
5511{
5512 //Apply instantly
5513 return RETURN_ERR;
5514}
5515
5516// set the authorization mode on this ap
5517// mode mapping as: 1: open, 2: shared, 4:auto
5518INT wifi_setApAuthMode(INT apIndex, INT mode)
5519{
developeraf95c502022-09-13 16:18:22 +08005520 struct params params={0};
5521 char config_file[64] = {0};
5522 int ret;
5523
5524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5525
5526 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5527 params.name = "auth_algs";
5528
developer72ec5572023-01-05 16:27:13 +08005529 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005530 params.value = "3";
5531 else if (mode & 2)
5532 params.value = "2";
5533 else if (mode & 1)
5534 params.value = "1";
5535 else
5536 params.value = "0";
5537
5538 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5539 wifi_hostapdWrite(config_file, &params, 1);
5540 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005541 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005542 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5543
5544 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005545}
5546
5547// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5548INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5549{
5550 //save to wifi config, and wait for wifi restart to apply
5551 struct params params={'\0'};
5552 char config_file[MAX_BUF_SIZE] = {0};
5553 int ret;
5554
5555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5556 if(authMode == NULL)
5557 return RETURN_ERR;
5558
5559 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5560 params.name = "wpa_key_mgmt";
5561
5562 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5563 params.value = "WPA-PSK";
5564 else if(strcmp(authMode,"EAPAuthentication") == 0)
5565 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005566 else if (strcmp(authMode, "SAEAuthentication") == 0)
5567 params.value = "SAE";
5568 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5569 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005570 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5571 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005572 else if (strcmp(authMode, "Enhanced_Open") == 0)
5573 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005574 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5575 return RETURN_OK; //This is taken careof in beaconType
5576
5577 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5578 ret=wifi_hostapdWrite(config_file,&params,1);
5579 if(!ret)
5580 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5581 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5582
5583 return ret;
5584}
5585
5586// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5587INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5588{
5589 //save to wifi config, and wait for wifi restart to apply
5590 char BeaconType[50] = {0};
5591 char config_file[MAX_BUF_SIZE] = {0};
5592
5593 *authMode = 0;
5594 wifi_getApBeaconType(apIndex,BeaconType);
5595 printf("%s____%s \n",__FUNCTION__,BeaconType);
5596
5597 if(strcmp(BeaconType,"None") == 0)
5598 strcpy(authMode,"None");
5599 else
5600 {
5601 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5602 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5603 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5604 if(strcmp(authMode,"WPA-PSK") == 0)
5605 strcpy(authMode,"SharedAuthentication");
5606 else if(strcmp(authMode,"WPA-EAP") == 0)
5607 strcpy(authMode,"EAPAuthentication");
5608 }
5609
5610 return RETURN_OK;
5611}
5612
5613// Outputs the number of stations associated per AP
5614INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5615{
developerd946fd62022-12-08 18:03:28 +08005616 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005617 char cmd[128]={0};
5618 char buf[128]={0};
5619 BOOL status = false;
5620
5621 if(apIndex > MAX_APS)
5622 return RETURN_ERR;
5623
5624 wifi_getApEnable(apIndex,&status);
5625 if (!status)
5626 return RETURN_OK;
5627
developerd946fd62022-12-08 18:03:28 +08005628 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005629 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005630 return RETURN_ERR;
5631 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005632 _syscmd(cmd, buf, sizeof(buf));
5633 sscanf(buf,"%lu", output_ulong);
5634
5635 return RETURN_OK;
5636}
5637
5638// manually removes any active wi-fi association with the device specified on this ap
5639INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5640{
developerd946fd62022-12-08 18:03:28 +08005641 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005642 char buf[126]={'\0'};
5643
developerac6f1142022-12-20 19:26:35 +08005644 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005645 return RETURN_ERR;
5646 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005647 system(buf);
5648
5649 return RETURN_OK;
5650}
5651
5652// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5653INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5654{
5655 if(NULL == output_int)
5656 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005657 int max_radio_num = 0;
5658 wifi_getMaxRadioNumber(&max_radio_num);
5659 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005660 return RETURN_OK;
5661}
5662
5663// sets the radio index for the specific ap
5664INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5665{
5666 //set to config only and wait for wifi reset to apply settings
5667 return RETURN_ERR;
5668}
5669
5670// Get the ACL MAC list per AP
5671INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5672{
developerd946fd62022-12-08 18:03:28 +08005673 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005674 char cmd[MAX_CMD_SIZE]={'\0'};
5675 int ret = 0;
5676
developerac6f1142022-12-20 19:26:35 +08005677 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005678 return RETURN_ERR;
5679 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005680 ret = _syscmd(cmd,macArray,buf_size);
5681 if (ret != 0)
5682 return RETURN_ERR;
5683
5684 return RETURN_OK;
5685}
5686
developere6aafda2022-09-13 14:59:28 +08005687INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5688{
developerd946fd62022-12-08 18:03:28 +08005689 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005690 char cmd[MAX_CMD_SIZE]={'\0'};
5691 int ret = 0;
5692
developerac6f1142022-12-20 19:26:35 +08005693 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005694 return RETURN_ERR;
5695 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005696 ret = _syscmd(cmd,macArray,buf_size);
5697 if (ret != 0)
5698 return RETURN_ERR;
5699
5700 return RETURN_OK;
5701}
5702
developer06a01d92022-09-07 16:32:39 +08005703// Get the list of stations associated per AP
5704INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5705{
developerd946fd62022-12-08 18:03:28 +08005706 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005707 char cmd[128];
5708
5709 if(apIndex > 3) //Currently supporting apIndex upto 3
5710 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005711 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005712 return RETURN_ERR;
5713 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5714 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005715 _syscmd(cmd, macArray, buf_size);
5716
5717 return RETURN_OK;
5718}
5719
developer2f995fb2023-02-24 10:40:44 +08005720INT getAddressControlMode(INT apIndex, INT *mode)
5721{
5722 char buf [16] = {0};
5723 char config_file[64] = {0};
5724
5725 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5726 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5727
5728 *mode = -1;
5729 // 0 use deny file, 1 use accept file
5730 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5731 *mode = (INT)strtol(buf, NULL, 10);
5732
5733 return RETURN_OK;
5734}
5735
developer06a01d92022-09-07 16:32:39 +08005736// adds the mac address to the filter list
5737//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5738INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5739{
5740 char cmd[MAX_CMD_SIZE]={'\0'};
5741 char buf[MAX_BUF_SIZE]={'\0'};
5742
developer2f995fb2023-02-24 10:40:44 +08005743 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005744 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005745
developer06a01d92022-09-07 16:32:39 +08005746 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5747 if(_syscmd(cmd,buf,sizeof(buf)))
5748 return RETURN_ERR;
5749
5750 return RETURN_OK;
5751}
5752
developer2f995fb2023-02-24 10:40:44 +08005753INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5754{
5755 char cmd[MAX_CMD_SIZE]={'\0'};
5756 char buf[MAX_BUF_SIZE]={'\0'};
5757
5758 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5759 return RETURN_ERR;
5760
5761 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5762 if(_syscmd(cmd,buf,sizeof(buf)))
5763 return RETURN_ERR;
5764
5765 return RETURN_OK;
5766}
5767
developer06a01d92022-09-07 16:32:39 +08005768// deletes the mac address from the filter list
5769//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5770INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5771{
5772 char cmd[MAX_CMD_SIZE]={'\0'};
5773 char buf[MAX_BUF_SIZE]={'\0'};
5774
5775#if 0
developerd946fd62022-12-08 18:03:28 +08005776 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005777 if(_syscmd(cmd,buf,sizeof(buf)))
5778 return RETURN_ERR;
5779
5780#endif
developer2f995fb2023-02-24 10:40:44 +08005781 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005782 if(_syscmd(cmd,buf,sizeof(buf)))
5783 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005784 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5785 if(_syscmd(cmd,buf,sizeof(buf)))
5786 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005787
5788 return RETURN_OK;
5789}
5790
5791// outputs the number of devices in the filter list
5792INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5793{
developere6aafda2022-09-13 14:59:28 +08005794 char cmd[MAX_BUF_SIZE]={0};
5795 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005796 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005797
5798 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5799 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005800 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005801
developer2f995fb2023-02-24 10:40:44 +08005802 getAddressControlMode(apIndex, &mode);
5803 if (mode == -1)
5804 return RETURN_OK;
5805
5806 if (mode == 0)
5807 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5808 else if (mode == 1)
5809 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005810 _syscmd(cmd, buf, sizeof(buf));
5811
developer2f995fb2023-02-24 10:40:44 +08005812 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005813
5814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5815 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005816}
5817
5818INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5819{
5820 char cmd[128]={'\0'};
5821 char buf[128]={'\0'};
5822
5823 if(strcmp(action,"DENY")==0)
5824 {
5825 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5826 system(buf);
5827 return RETURN_OK;
5828 }
5829
5830 if(strcmp(action,"ALLOW")==0)
5831 {
5832 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5833 system(buf);
5834 return RETURN_OK;
5835 }
5836
5837 return RETURN_ERR;
5838
5839}
5840
5841// enable kick for devices on acl black list
5842INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5843{
5844 char aclArray[512] = {0}, *acl = NULL;
5845 char assocArray[512] = {0}, *asso = NULL;
5846
developere6aafda2022-09-13 14:59:28 +08005847 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005848 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5849
5850 // if there are no devices connected there is nothing to do
5851 if (strlen(assocArray) < 17)
5852 return RETURN_OK;
5853
5854 if (enable == TRUE)
5855 {
5856 //kick off the MAC which is in ACL array (deny list)
5857 acl = strtok(aclArray, "\r\n");
5858 while (acl != NULL) {
5859 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5860 wifi_kickApAssociatedDevice(apIndex, acl);
5861
5862 acl = strtok(NULL, "\r\n");
5863 }
developere6aafda2022-09-13 14:59:28 +08005864 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005865 }
5866 else
5867 {
developere6aafda2022-09-13 14:59:28 +08005868 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005869 }
5870
5871#if 0
5872 //TODO: need to revisit below implementation
5873 char aclArray[512]={0}, *acl=NULL;
5874 char assocArray[512]={0}, *asso=NULL;
5875 char buf[256]={'\0'};
5876 char action[10]={'\0'};
5877 FILE *fr=NULL;
5878 char interface[10]={'\0'};
5879 char config_file[MAX_BUF_SIZE] = {0};
5880
5881 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5882 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5883 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5884 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5885
5886 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5887 system(buf);
5888 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5889 system(buf);
5890 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5891 system(buf);
5892 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5893 system(buf);
5894 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5895 system(buf);
5896
5897 if ( enable == TRUE )
5898 {
5899 int device_count=0;
5900 strcpy(action,"DENY");
5901 //kick off the MAC which is in ACL array (deny list)
5902 acl = strtok (aclArray,",");
5903 while (acl != NULL) {
5904 if(strlen(acl)>=17)
5905 {
5906 apply_rules(apIndex, acl,action,interface);
5907 device_count++;
5908 //Register mac to be blocked ,in syscfg.db persistent storage
5909 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5910 system(buf);
5911 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5912 system(buf);
5913 system("syscfg commit");
5914
5915 wifi_kickApAssociatedDevice(apIndex, acl);
5916 }
5917 acl = strtok (NULL, ",");
5918 }
5919 }
5920 else
5921 {
5922 int device_count=0;
5923 char cmdmac[20]={'\0'};
5924 strcpy(action,"ALLOW");
5925 //kick off the MAC which is not in ACL array (allow list)
5926 acl = strtok (aclArray,",");
5927 while (acl != NULL) {
5928 if(strlen(acl)>=17)
5929 {
5930 apply_rules(apIndex, acl,action,interface);
5931 device_count++;
5932 //Register mac to be Allowed ,in syscfg.db persistent storage
5933 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5934 system(buf);
5935 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5936 system(buf);
5937 sprintf(cmdmac,"%s",acl);
5938 }
5939 acl = strtok (NULL, ",");
5940 }
5941 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5942 system(buf);
5943
5944 //Disconnect the mac which is not in ACL
5945 asso = strtok (assocArray,",");
5946 while (asso != NULL) {
5947 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5948 wifi_kickApAssociatedDevice(apIndex, asso);
5949 asso = strtok (NULL, ",");
5950 }
5951 }
5952#endif
5953 return RETURN_OK;
5954}
5955
5956INT wifi_setPreferPrivateConnection(BOOL enable)
5957{
developer06a01d92022-09-07 16:32:39 +08005958 return RETURN_OK;
5959}
5960
5961// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5962INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5963{
developerd946fd62022-12-08 18:03:28 +08005964 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005965 int items = 1;
5966 struct params list[2];
5967 char buf[MAX_BUF_SIZE] = {0};
5968 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005969 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005970
5971 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005972
developer10adcc12022-09-13 14:39:17 +08005973 if (filterMode == 0) {
5974 sprintf(buf, "%d", 0);
5975 list[0].value = buf;
5976
developer2f995fb2023-02-24 10:40:44 +08005977 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08005978 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005979 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005980 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
5981 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08005982 memset(cmd,0,sizeof(cmd));
5983 // Delete deny_mac_file in hostapd configuration
5984 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08005985 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08005986 }
5987 else if (filterMode == 1) {
5988 sprintf(buf, "%d", filterMode);
5989 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005990 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5991 list[1].name = "accept_mac_file";
5992 list[1].value = acl_file;
5993 items = 2;
developer10adcc12022-09-13 14:39:17 +08005994 } else if (filterMode == 2) {
5995 //TODO: deny_mac_file
5996 sprintf(buf, "%d", 0);
5997 list[0].value = buf;
5998 list[1].name = "deny_mac_file";
5999 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
6000 list[1].value = deny_file;
6001 items = 2;
6002 } else {
6003 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006004 }
developer10adcc12022-09-13 14:39:17 +08006005
developer06a01d92022-09-07 16:32:39 +08006006 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6007 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08006008 if (multiple_set == FALSE) {
6009 wifi_setApEnable(apIndex, FALSE);
6010 wifi_setApEnable(apIndex, TRUE);
6011 }
developer06a01d92022-09-07 16:32:39 +08006012
6013 return RETURN_OK;
6014
6015#if 0
6016 if(apIndex==0 || apIndex==1)
6017 {
6018 //set the filtermode
6019 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
6020 system(buf);
6021 system("syscfg commit");
6022
6023 if(filterMode==0)
6024 {
6025 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6026 system(buf);
6027 return RETURN_OK;
6028 }
6029 }
6030 return RETURN_OK;
6031#endif
6032}
6033
6034// 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.
6035INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6036{
6037 return RETURN_ERR;
6038}
6039
6040// gets the vlan ID for this ap from an internal enviornment variable
6041INT wifi_getApVlanID(INT apIndex, INT *output_int)
6042{
developer30423732022-12-01 16:17:49 +08006043 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08006044 {
6045 *output_int=100;
6046 return RETURN_OK;
6047 }
6048
6049 return RETURN_ERR;
6050}
6051
6052// sets the vlan ID for this ap to an internal enviornment variable
6053INT wifi_setApVlanID(INT apIndex, INT vlanId)
6054{
6055 //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)
6056 return RETURN_ERR;
6057}
6058
6059// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6060INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6061{
6062 snprintf(bridgeName, 32, "brlan0");
6063 snprintf(IP, 32, "10.0.0.1");
6064 snprintf(subnet, 32, "255.255.255.0");
6065
6066 return RETURN_OK;
6067}
6068
6069//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6070INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6071{
6072 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6073 return RETURN_ERR;
6074}
6075
6076// reset the vlan configuration for this ap
6077INT wifi_resetApVlanCfg(INT apIndex)
6078{
developerf5fef612022-09-20 19:38:26 +08006079 char original_config_file[64] = {0};
6080 char current_config_file[64] = {0};
6081 char buf[64] = {0};
6082 char cmd[64] = {0};
6083 char vlan_file[64] = {0};
6084 char vlan_tagged_interface[16] = {0};
6085 char vlan_bridge[16] = {0};
6086 char vlan_naming[16] = {0};
6087 struct params list[4] = {0};
6088 wifi_band band;
6089
6090 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6091
6092 band = wifi_index_to_band(apIndex);
6093 if (band == band_2_4)
6094 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006095 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006096 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006097 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006098 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6099
6100 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6101
6102 if (strlen(vlan_file) == 0)
6103 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006104
developerf5fef612022-09-20 19:38:26 +08006105 // The file should exist or this vap would not work.
6106 if (access(vlan_file, F_OK) != 0) {
6107 sprintf(cmd, "touch %s", vlan_file);
6108 _syscmd(cmd, buf, sizeof(buf));
6109 }
6110 list[0].name = "vlan_file";
6111 list[0].value = vlan_file;
6112
6113 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6114 list[1].name = "vlan_tagged_interface";
6115 list[1].value = vlan_tagged_interface;
6116
6117 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6118 list[2].name = "vlan_bridge";
6119 list[2].value = vlan_bridge;
6120
6121 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6122 list[3].name = "vlan_naming";
6123 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006124
developerf5fef612022-09-20 19:38:26 +08006125 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6126 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006127 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006128 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006129
developerf5fef612022-09-20 19:38:26 +08006130 // restart this ap
6131 wifi_setApEnable(apIndex, FALSE);
6132 wifi_setApEnable(apIndex, TRUE);
6133
6134 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6135
6136 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006137}
6138
6139// 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.
6140INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6141{
6142 return RETURN_ERR;
6143}
6144
6145// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6146INT wifi_startHostApd()
6147{
6148 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6149 system("systemctl start hostapd.service");
6150 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6151 return RETURN_OK;
6152 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6153}
6154
6155// stops hostapd
6156INT wifi_stopHostApd()
6157{
6158 char cmd[128] = {0};
6159 char buf[128] = {0};
6160
6161 sprintf(cmd,"systemctl stop hostapd");
6162 _syscmd(cmd, buf, sizeof(buf));
6163
6164 return RETURN_OK;
6165}
6166
6167// restart hostapd dummy function
6168INT wifi_restartHostApd()
6169{
6170 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6171 system("systemctl restart hostapd-global");
6172 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6173
6174 return RETURN_OK;
6175}
6176
6177static int align_hostapd_config(int index)
6178{
6179 ULONG lval;
6180 wifi_getRadioChannel(index%2, &lval);
6181 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006182 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006183}
6184
6185// sets the AP enable status variable for the specified ap.
6186INT wifi_setApEnable(INT apIndex, BOOL enable)
6187{
developerd946fd62022-12-08 18:03:28 +08006188 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006189 char config_file[MAX_BUF_SIZE] = {0};
6190 char cmd[MAX_CMD_SIZE] = {0};
6191 char buf[MAX_BUF_SIZE] = {0};
6192 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006193 int max_radio_num = 0;
6194 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006195
6196 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006197
6198 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006199 if (enable == status)
6200 return RETURN_OK;
6201
developerac6f1142022-12-20 19:26:35 +08006202 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006203 return RETURN_ERR;
6204
developer06a01d92022-09-07 16:32:39 +08006205 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006206 int radioIndex = apIndex % max_radio_num;
6207 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006208 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6209 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006210 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006211 _syscmd(cmd, buf, sizeof(buf));
developer2f18b9f2023-03-17 19:32:57 +08006212 if (!(apIndex/max_radio_num)) {
6213 sprintf(cmd, "iw %s del", interface_name);
6214 _syscmd(cmd, buf, sizeof(buf));
6215 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6216 _syscmd(cmd, buf, sizeof(buf));
6217 }
developer033b37b2022-10-18 11:27:46 +08006218 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006219 _syscmd(cmd, buf, sizeof(buf));
6220 }
6221 else {
developerd946fd62022-12-08 18:03:28 +08006222 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006223 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006224 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006225 _syscmd(cmd, buf, sizeof(buf));
6226 }
developera77d84b2023-02-22 16:10:50 +08006227
developer431128d2022-12-16 15:30:41 +08006228 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006229 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006230 _syscmd(cmd, buf, sizeof(buf));
6231 //Wait for wifi up/down to apply
6232 return RETURN_OK;
6233}
6234
6235// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6236INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6237{
developerd946fd62022-12-08 18:03:28 +08006238 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006239 char cmd[MAX_CMD_SIZE] = {'\0'};
6240 char buf[MAX_BUF_SIZE] = {'\0'};
6241
6242 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6243 return RETURN_ERR;
6244
6245 *output_bool = 0;
6246
6247 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6248 {
developerac6f1142022-12-20 19:26:35 +08006249 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006250 *output_bool = FALSE;
6251 return RETURN_OK;
6252 }
6253 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006254 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6255 }
6256
6257 return RETURN_OK;
6258}
6259
6260// Outputs the AP "Enabled" "Disabled" status from driver
6261INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6262{
6263 char cmd[128] = {0};
6264 char buf[128] = {0};
6265 BOOL output_bool;
6266
6267 if ( NULL == output_string)
6268 return RETURN_ERR;
6269 wifi_getApEnable(apIndex,&output_bool);
6270
6271 if(output_bool == 1)
6272 snprintf(output_string, 32, "Up");
6273 else
6274 snprintf(output_string, 32, "Disable");
6275
6276 return RETURN_OK;
6277}
6278
6279//Indicates whether or not beacons include the SSID name.
6280// outputs a 1 if SSID on the AP is enabled, else outputs 0
6281INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6282{
6283 //get the running status
6284 char config_file[MAX_BUF_SIZE] = {0};
6285 char buf[16] = {0};
6286
6287 if (!output)
6288 return RETURN_ERR;
6289
6290 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6291 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006292 // default is enable
6293 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6294 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006295
6296 return RETURN_OK;
6297}
6298
6299// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6300INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6301{
6302 //store the config, apply instantly
6303 char config_file[MAX_BUF_SIZE] = {0};
6304 struct params list;
6305
6306 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6307 list.name = "ignore_broadcast_ssid";
6308 list.value = enable?"0":"1";
6309
6310 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6311 wifi_hostapdWrite(config_file, &list, 1);
6312 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6313 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006314 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08006315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6316
6317 return RETURN_OK;
6318}
6319
6320//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6321INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6322{
6323 //get the running status
6324 if(!output_uint)
6325 return RETURN_ERR;
6326 *output_uint=16;
6327 return RETURN_OK;
6328}
6329
6330INT wifi_setApRetryLimit(INT apIndex, UINT number)
6331{
6332 //apply instantly
6333 return RETURN_ERR;
6334}
6335
6336//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6337INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6338{
6339 if(!output)
6340 return RETURN_ERR;
6341 *output=TRUE;
6342 return RETURN_OK;
6343}
6344
6345//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6346INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6347{
6348 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006349 char cmd[128] = {0};
6350 char buf[128] = {0};
6351 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006352 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006353
developer0b246d12022-09-30 15:24:20 +08006354 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006355
developer0b246d12022-09-30 15:24:20 +08006356 wifi_getMaxRadioNumber(&max_radio_num);
6357 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006358 phyId = radio_index_to_phy(radioIndex);
6359 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006360 _syscmd(cmd,buf, sizeof(buf));
6361
6362 if (strlen(buf) > 0)
6363 *output = true;
6364
6365 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006366
developer06a01d92022-09-07 16:32:39 +08006367 return RETURN_OK;
6368}
6369
6370//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6371INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6372{
6373 //get the running status from driver
6374 if(!output)
6375 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006376
6377 char config_file[MAX_BUF_SIZE] = {0};
6378 char buf[16] = {0};
6379
6380 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6381 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006382 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006383 *output = TRUE;
6384 else
6385 *output = FALSE;
6386
developer06a01d92022-09-07 16:32:39 +08006387 return RETURN_OK;
6388}
6389
6390// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6391INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6392{
6393 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006394 char config_file[MAX_BUF_SIZE] = {0};
6395 struct params list;
6396
6397 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6398 list.name = "wmm_enabled";
6399 list.value = enable?"1":"0";
6400
6401 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6402 wifi_hostapdWrite(config_file, &list, 1);
6403 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6404 wifi_reloadAp(apIndex);
6405 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6406
6407 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006408}
6409
6410//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.
6411INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6412{
6413 //get the running status from driver
6414 if(!output)
6415 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006416
6417 char config_file[128] = {0};
6418 char buf[16] = {0};
6419
6420 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6421 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6422 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6423 *output = TRUE;
6424 else
6425 *output = FALSE;
6426
developer06a01d92022-09-07 16:32:39 +08006427 return RETURN_OK;
6428}
6429
6430// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6431INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6432{
6433 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006434 char config_file[MAX_BUF_SIZE] = {0};
6435 struct params list;
6436
6437 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6438 list.name = "uapsd_advertisement_enabled";
6439 list.value = enable?"1":"0";
6440
6441 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6442 wifi_hostapdWrite(config_file, &list, 1);
6443 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6444 wifi_reloadAp(apIndex);
6445 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6446
6447 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006448}
6449
developer6daeb3f2022-09-30 13:36:39 +08006450// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006451INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6452{
developerd946fd62022-12-08 18:03:28 +08006453 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006454 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6455 char cmd[128] = {0};
6456 char buf[128] = {0};
6457 char ack_filepath[128] = {0};
6458 uint16_t bitmap = 0;
6459 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6460 FILE *f = NULL;
6461
6462 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6463
6464 // Get current setting
6465 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6466 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6467 _syscmd(cmd, buf, sizeof(buf));
6468 if (strlen(buf) > 0)
6469 bitmap = strtoul(buf, NULL, 10);
6470
6471 bitmap = strtoul(buf, NULL, 10);
6472
6473 if (ackPolicy == TRUE) { // True, unset this class
6474 bitmap &= ~class_map[class];
6475 } else { // False, set this class
6476 bitmap |= class_map[class];
6477 }
6478
6479 f = fopen(ack_filepath, "w");
6480 if (f == NULL) {
6481 fprintf(stderr, "%s: fopen failed\n", __func__);
6482 return RETURN_ERR;
6483 }
6484 fprintf(f, "%hu", bitmap);
6485 fclose(f);
6486
developerac6f1142022-12-20 19:26:35 +08006487 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006488 return RETURN_ERR;
6489 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006490 _syscmd(cmd, buf, sizeof(buf));
6491
6492 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6493 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006494}
6495
6496//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.
6497INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6498{
6499 //get the running status from driver
6500 if(!output_uint)
6501 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006502
6503 char output[16]={'\0'};
6504 char config_file[MAX_BUF_SIZE] = {0};
6505
6506 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6507 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6508 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6509 else {
6510 int device_num = atoi(output);
6511 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6512 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6513 return RETURN_ERR;
6514 }
6515 else {
6516 *output_uint = device_num;
6517 }
6518 }
6519
developer06a01d92022-09-07 16:32:39 +08006520 return RETURN_OK;
6521}
6522
6523INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6524{
6525 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006526 char str[MAX_BUF_SIZE]={'\0'};
6527 char cmd[MAX_CMD_SIZE]={'\0'};
6528 struct params params;
6529 char config_file[MAX_BUF_SIZE] = {0};
6530
6531 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006532 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006533 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006534 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006535 }
6536 sprintf(str, "%d", number);
6537 params.name = "max_num_sta";
6538 params.value = str;
6539
6540 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6541 int ret = wifi_hostapdWrite(config_file, &params, 1);
6542 if (ret) {
6543 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6544 ,__func__, ret);
6545 }
6546
6547 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6548 if (ret) {
6549 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6550 ,__func__, ret);
6551 }
6552 wifi_reloadAp(apIndex);
6553 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6554
6555 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006556}
6557
6558//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.
6559INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6560{
6561 //get the current threshold
6562 if(!output_uint)
6563 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006564 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6565 if (*output_uint == 0)
6566 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006567 return RETURN_OK;
6568}
6569
6570INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6571{
6572 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006573 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6574 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006575 return RETURN_ERR;
6576}
6577
6578//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.
6579INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6580{
6581 if(!output_uint)
6582 return RETURN_ERR;
6583 *output_uint = 3;
6584 return RETURN_OK;
6585}
6586
6587//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6588INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6589{
6590 if(!output_uint)
6591 return RETURN_ERR;
6592 *output_uint = 3;
6593 return RETURN_OK;
6594}
6595
6596//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.
6597INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6598{
6599 if(!output_in_seconds)
6600 return RETURN_ERR;
6601 *output_in_seconds = 0;
6602 return RETURN_OK;
6603}
6604
6605//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
6606INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6607{
6608 if(!output || apIndex>=MAX_APS)
6609 return RETURN_ERR;
6610 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006611 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006612 return RETURN_OK;
6613}
6614
6615//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6616INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6617{
developer587c1b62022-09-27 15:58:59 +08006618 char config_file[128] = {0};
6619 char wpa[16] = {0};
6620 char key_mgmt[64] = {0};
6621 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006622 if (!output)
6623 return RETURN_ERR;
6624
6625 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006626 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006627
developer587c1b62022-09-27 15:58:59 +08006628 strcpy(output, "None");//Copying "None" to output string for default case
6629 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006630 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006631 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006632 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006633 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006634 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006635 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006636 snprintf(output, 32, "WPA-WPA2-Personal");
6637
developer72ec5572023-01-05 16:27:13 +08006638 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6639 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006640 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006641 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006642 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006643 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006644 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006645 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006646 snprintf(output, 32, "WPA-WPA2-Enterprise");
6647 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006648 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006649 snprintf(output, 32, "WPA3-Personal");
6650 else
developer4a359672022-10-13 15:30:46 +08006651 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006652 }
developer06a01d92022-09-07 16:32:39 +08006653
6654 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6655 return RETURN_OK;
6656#if 0
6657 //TODO: need to revisit below implementation
6658 char securityType[32], authMode[32];
6659 int enterpriseMode=0;
6660
6661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6662 if(!output)
6663 return RETURN_ERR;
6664
6665 wifi_getApBeaconType(apIndex, securityType);
6666 strcpy(output,"None");//By default, copying "None" to output string
6667 if (strncmp(securityType,"None", strlen("None")) == 0)
6668 return RETURN_OK;
6669
6670 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6671 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6672
6673 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6674 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6675 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6676 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6677 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6678 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6679 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6680
6681 return RETURN_OK;
6682#endif
6683}
6684
6685INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6686{
6687 char securityType[32];
6688 char authMode[32];
6689
6690 //store settings and wait for wifi up to apply
6691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6692 if(!encMode)
6693 return RETURN_ERR;
6694
developer06a01d92022-09-07 16:32:39 +08006695 if (strcmp(encMode, "None")==0)
6696 {
6697 strcpy(securityType,"None");
6698 strcpy(authMode,"None");
6699 }
6700 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6701 {
6702 strcpy(securityType,"WPAand11i");
6703 strcpy(authMode,"PSKAuthentication");
6704 }
6705 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6706 {
6707 strcpy(securityType,"WPAand11i");
6708 strcpy(authMode,"EAPAuthentication");
6709 }
6710 else if (strcmp(encMode, "WPA-Personal")==0)
6711 {
6712 strcpy(securityType,"WPA");
6713 strcpy(authMode,"PSKAuthentication");
6714 }
6715 else if (strcmp(encMode, "WPA-Enterprise")==0)
6716 {
6717 strcpy(securityType,"WPA");
6718 strcpy(authMode,"EAPAuthentication");
6719 }
6720 else if (strcmp(encMode, "WPA2-Personal")==0)
6721 {
6722 strcpy(securityType,"11i");
6723 strcpy(authMode,"PSKAuthentication");
6724 }
6725 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6726 {
6727 strcpy(securityType,"11i");
6728 strcpy(authMode,"EAPAuthentication");
6729 }
developer587c1b62022-09-27 15:58:59 +08006730 else if (strcmp(encMode, "WPA3-Personal") == 0)
6731 {
6732 strcpy(securityType,"11i");
6733 strcpy(authMode,"SAEAuthentication");
6734 }
developer4a359672022-10-13 15:30:46 +08006735 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006736 {
6737 strcpy(securityType, "11i");
6738 strcpy(authMode, "PSK-SAEAuthentication");
6739 }
developer587c1b62022-09-27 15:58:59 +08006740 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6741 {
6742 strcpy(securityType,"11i");
6743 strcpy(authMode,"EAP_192-bit_Authentication");
6744 }
developer5c9fee82023-01-13 14:44:16 +08006745 else if (strcmp(encMode, "OWE") == 0)
6746 {
6747 strcpy(securityType,"11i");
6748 strcpy(authMode,"Enhanced_Open");
6749 }
developer06a01d92022-09-07 16:32:39 +08006750 else
6751 {
6752 strcpy(securityType,"None");
6753 strcpy(authMode,"None");
6754 }
6755 wifi_setApBeaconType(apIndex, securityType);
6756 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6758
6759 return RETURN_OK;
6760}
6761
6762
developer4b102122023-02-15 10:53:03 +08006763// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006764//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006765INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6766{
developer30423732022-12-01 16:17:49 +08006767 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006768 char config_file[MAX_BUF_SIZE] = {0};
6769
6770 if(output_string==NULL)
6771 return RETURN_ERR;
6772
6773 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6774 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6775
6776 if(strcmp(buf,"0")==0)
6777 {
6778 printf("wpa_mode is %s ......... \n",buf);
6779 return RETURN_ERR;
6780 }
6781
6782 wifi_dbg_printf("\nFunc=%s\n",__func__);
6783 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006784 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006785 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6786
6787 return RETURN_OK;
6788}
6789
developer4b102122023-02-15 10:53:03 +08006790// Set PreSharedKey associated with a Access Point.
6791// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006792INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6793{
6794 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6795 struct params params={'\0'};
6796 int ret;
6797 char config_file[MAX_BUF_SIZE] = {0};
6798
6799 if(NULL == preSharedKey)
6800 return RETURN_ERR;
6801
developer4b102122023-02-15 10:53:03 +08006802 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006803
developer4b102122023-02-15 10:53:03 +08006804 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006805 {
developer4b102122023-02-15 10:53:03 +08006806 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006807 return RETURN_ERR;
6808 }
6809 params.value = preSharedKey;
6810 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6811 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006812 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006813 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006814 wifi_reloadAp(apIndex);
6815 }
developer06a01d92022-09-07 16:32:39 +08006816 return ret;
6817 //TODO: call hostapd_cli for dynamic_config_control
6818}
6819
6820//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6821// outputs the passphrase, maximum 63 characters
6822INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6823{
6824 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6825
6826 wifi_dbg_printf("\nFunc=%s\n",__func__);
6827 if (NULL == output_string)
6828 return RETURN_ERR;
6829
6830 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6831 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6832 if(strcmp(buf,"0")==0)
6833 {
6834 printf("wpa_mode is %s ......... \n",buf);
6835 return RETURN_ERR;
6836 }
6837
6838 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6839 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6840
6841 return RETURN_OK;
6842}
6843
6844// sets the passphrase enviornment variable, max 63 characters
6845INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6846{
6847 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6848 struct params params={'\0'};
6849 char config_file[MAX_BUF_SIZE] = {0};
6850 int ret;
6851
6852 if(NULL == passPhrase)
6853 return RETURN_ERR;
6854
6855 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6856 {
6857 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6858 return RETURN_ERR;
6859 }
6860 params.name = "wpa_passphrase";
6861 params.value = passPhrase;
6862 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6863 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006864 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006865 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006866 wifi_reloadAp(apIndex);
6867 }
developer06a01d92022-09-07 16:32:39 +08006868
6869 return ret;
6870}
6871
6872//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.
6873INT wifi_setApSecurityReset(INT apIndex)
6874{
developer8d583982022-09-20 11:28:22 +08006875 char original_config_file[64] = {0};
6876 char current_config_file[64] = {0};
6877 char buf[64] = {0};
6878 char cmd[64] = {0};
6879 char wpa[4] = {0};
6880 char wpa_psk[64] = {0};
6881 char wpa_passphrase[64] = {0};
6882 char wpa_psk_file[128] = {0};
6883 char wpa_key_mgmt[64] = {0};
6884 char wpa_pairwise[32] = {0};
6885 wifi_band band;
6886 struct params list[6];
6887
6888 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6889
6890 band = wifi_index_to_band(apIndex);
6891 if (band == band_2_4)
6892 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006893 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006894 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006895 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006896 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6897 else
6898 return RETURN_ERR;
6899
6900 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6901 list[0].name = "wpa";
6902 list[0].value = wpa;
6903
6904 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6905 list[1].name = "wpa_psk";
6906 list[1].value = wpa_psk;
6907
6908 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6909 list[2].name = "wpa_passphrase";
6910 list[2].value = wpa_passphrase;
6911
6912 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6913
6914 if (strlen(wpa_psk_file) == 0)
6915 strcpy(wpa_psk_file, PSK_FILE);
6916
6917 if (access(wpa_psk_file, F_OK) != 0) {
6918 sprintf(cmd, "touch %s", wpa_psk_file);
6919 _syscmd(cmd, buf, sizeof(buf));
6920 }
6921 list[3].name = "wpa_psk_file";
6922 list[3].value = wpa_psk_file;
6923
6924 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6925 list[4].name = "wpa_key_mgmt";
6926 list[4].value = wpa_key_mgmt;
6927
6928 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6929 list[5].name = "wpa_pairwise";
6930 list[5].value = wpa_pairwise;
6931
6932 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6933 wifi_hostapdWrite(current_config_file, list, 6);
6934
6935 wifi_setApEnable(apIndex, FALSE);
6936 wifi_setApEnable(apIndex, TRUE);
6937
6938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6939 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006940}
6941
6942//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).
6943INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6944{
developer8f2ddd52022-09-13 15:39:24 +08006945 char config_file[64] = {0};
6946 char buf[64] = {0};
6947 char cmd[256] = {0};
6948
6949 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6950
developer06a01d92022-09-07 16:32:39 +08006951 if(!IP_output || !Port_output || !RadiusSecret_output)
6952 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006953
developer8f2ddd52022-09-13 15:39:24 +08006954 // Read the first matched config
6955 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6956 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6957 _syscmd(cmd, buf, sizeof(buf));
6958 strncpy(IP_output, buf, 64);
6959
6960 memset(buf, 0, sizeof(buf));
6961 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6962 _syscmd(cmd, buf, sizeof(buf));
6963 *Port_output = atoi(buf);
6964
6965 memset(buf, 0, sizeof(buf));
6966 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6967 _syscmd(cmd, buf, sizeof(buf));
6968 strncpy(RadiusSecret_output, buf, 64);
6969
6970 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006971 return RETURN_OK;
6972}
6973
6974INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6975{
developer8f2ddd52022-09-13 15:39:24 +08006976 char config_file[64] = {0};
6977 char port_str[8] = {0};
6978 char cmd[256] = {0};
6979 char buf[128] = {0};
6980
6981 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08006982 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
6983 return RETURN_ERR;
6984
6985 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
6986 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006987
6988 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6989
6990 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6991 _syscmd(cmd, buf, sizeof(buf));
6992 memset(cmd, 0, sizeof(cmd));
6993
6994 snprintf(port_str, sizeof(port_str), "%d", port);
6995 if (strlen(buf) == 0)
6996 // Append
6997 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6998 "auth_server_addr=%s\\n"
6999 "auth_server_port=%s\\n"
7000 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7001 else {
7002 // Delete the three lines setting after the "# radius 1" comment
7003 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7004 _syscmd(cmd, buf, sizeof(buf));
7005 memset(cmd, 0, sizeof(cmd));
7006 // Use "# radius 1" comment to find the location to insert the radius setting
7007 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7008 "# radius 1\\n"
7009 "auth_server_addr=%s\\n"
7010 "auth_server_port=%s\\n"
7011 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7012 }
7013 if(_syscmd(cmd, buf, sizeof(buf))) {
7014 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7015 return RETURN_ERR;
7016 }
7017
7018 wifi_reloadAp(apIndex);
7019 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7020 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007021}
7022
7023INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7024{
developer8f2ddd52022-09-13 15:39:24 +08007025 char config_file[64] = {0};
7026 char buf[64] = {0};
7027 char cmd[256] = {0};
7028
7029 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7030
developer06a01d92022-09-07 16:32:39 +08007031 if(!IP_output || !Port_output || !RadiusSecret_output)
7032 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007033
7034 // Read the second matched config
7035 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7036 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7037 _syscmd(cmd, buf, sizeof(buf));
7038 strncpy(IP_output, buf, 64);
7039
7040 memset(buf, 0, sizeof(buf));
7041 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7042 _syscmd(cmd, buf, sizeof(buf));
7043 *Port_output = atoi(buf);
7044
7045 memset(buf, 0, sizeof(buf));
7046 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7047 _syscmd(cmd, buf, sizeof(buf));
7048 strncpy(RadiusSecret_output, buf, 64);
7049
7050 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007051 return RETURN_OK;
7052}
7053
7054INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7055{
developer8f2ddd52022-09-13 15:39:24 +08007056 char config_file[64] = {0};
7057 char port_str[8] = {0};
7058 char cmd[256] = {0};
7059 char buf[128] = {0};
7060
7061 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007062 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7063 return RETURN_ERR;
7064
7065 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7066 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007067
7068 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7069
7070 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7071 _syscmd(cmd, buf, sizeof(buf));
7072 memset(cmd, 0, sizeof(cmd));
7073
7074 snprintf(port_str, sizeof(port_str), "%d", port);
7075 if (strlen(buf) == 0)
7076 // Append
7077 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7078 "auth_server_addr=%s\\n"
7079 "auth_server_port=%s\\n"
7080 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7081 else {
7082 // Delete the three lines setting after the "# radius 2" comment
7083 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7084 _syscmd(cmd, buf, sizeof(buf));
7085 memset(cmd, 0, sizeof(cmd));
7086 // Use "# radius 2" comment to find the location to insert the radius setting
7087 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7088 "# radius 2\\n"
7089 "auth_server_addr=%s\\n"
7090 "auth_server_port=%s\\n"
7091 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7092 }
7093 if(_syscmd(cmd, buf, sizeof(buf))) {
7094 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7095 return RETURN_ERR;
7096 }
7097
7098 wifi_reloadAp(apIndex);
7099 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7100 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007101}
7102
7103//RadiusSettings
7104INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7105{
7106 if(!output)
7107 return RETURN_ERR;
7108
7109 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7110 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7111 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7112 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7113 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7114 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.
7115 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7116 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7117 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7118 //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.
7119
7120 return RETURN_OK;
7121}
7122
7123INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7124{
7125 //store the paramters, and apply instantly
7126 return RETURN_ERR;
7127}
7128
7129//Device.WiFi.AccessPoint.{i}.WPS.Enable
7130//Enables or disables WPS functionality for this access point.
7131// outputs the WPS enable state of this ap in output_bool
7132INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7133{
developerd946fd62022-12-08 18:03:28 +08007134 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007135 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer613892e2023-09-21 16:33:35 +08007136
7137 *output_bool=FALSE;
developer5b398df2022-11-17 20:39:48 +08007138 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007139 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007140 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer613892e2023-09-21 16:33:35 +08007141 return RETURN_OK;
developerd946fd62022-12-08 18:03:28 +08007142 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007143 _syscmd(cmd, buf, sizeof(buf));
7144 if(strstr(buf, "configured"))
7145 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08007146
7147 return RETURN_OK;
developer613892e2023-09-21 16:33:35 +08007148}
developer06a01d92022-09-07 16:32:39 +08007149
7150//Device.WiFi.AccessPoint.{i}.WPS.Enable
7151// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7152INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7153{
7154 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007155 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007156 struct params params;
7157
developer06a01d92022-09-07 16:32:39 +08007158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7159 //store the paramters, and wait for wifi up to apply
7160 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007161 if (enable == TRUE) {
7162 wifi_getApBeaconType(apIndex, buf);
7163 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7164 params.value = "1";
7165 else // If ap set encryption
7166 params.value = "2";
7167 } else {
7168 params.value = "0";
7169 }
developer06a01d92022-09-07 16:32:39 +08007170
7171 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7172 wifi_hostapdWrite(config_file, &params, 1);
7173 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7174 wifi_reloadAp(apIndex);
7175
7176 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7177 return RETURN_OK;
7178}
7179
7180//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
7181INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7182{
7183 if(!output)
7184 return RETURN_ERR;
7185 snprintf(output, 128, "PushButton,PIN");
7186 return RETURN_OK;
7187}
7188
7189//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7190//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.
7191// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7192INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7193{
7194 if(!output)
7195 return RETURN_ERR;
7196 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7197
7198 return RETURN_OK;
7199}
7200
7201//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7202// 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
7203INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7204{
7205 //apply instantly. No setting need to be stored.
7206 char methods[MAX_BUF_SIZE], *token, *next_token;
7207 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7208 struct params params;
7209
developer5b398df2022-11-17 20:39:48 +08007210 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007211 return RETURN_ERR;
7212 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7213 //store the paramters, and wait for wifi up to apply
7214
7215 snprintf(methods, sizeof(methods), "%s", methodString);
7216 for(token=methods; *token; token=next_token)
7217 {
7218 strtok_r(token, ",", &next_token);
7219 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7220 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7221 else if(*token=='E')
7222 {
7223 if(!strcmp(methods, "Ethernet"))
7224 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7225 else if(!strcmp(methods, "ExternalNFCToken"))
7226 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7227 else
7228 printf("%s: Unknown WpsConfigMethod\n", __func__);
7229 }
7230 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7231 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7232 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7233 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7234 else if(*token=='P' )
7235 {
7236 if(!strcmp(token, "PushButton"))
developer894affa2023-05-10 18:13:19 +08007237 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer06a01d92022-09-07 16:32:39 +08007238 else if(!strcmp(token, "PIN"))
7239 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7240 else
7241 printf("%s: Unknown WpsConfigMethod\n", __func__);
7242 }
7243 else
7244 printf("%s: Unknown WpsConfigMethod\n", __func__);
7245 }
7246 params.name = "config_methods";
7247 params.value = config_methods;
7248 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7249 wifi_hostapdWrite(config_file, &params, 1);
7250 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7251 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7252
7253 return RETURN_OK;
7254}
7255
7256// outputs the pin value, ulong_pin must be allocated by the caller
7257INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7258{
7259 char buf[MAX_BUF_SIZE] = {0};
7260 char cmd[MAX_CMD_SIZE] = {0};
7261
developer5b398df2022-11-17 20:39:48 +08007262 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007263 return RETURN_ERR;
7264 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7265 _syscmd(cmd, buf, sizeof(buf));
7266 if(strlen(buf) > 0)
7267 *output_ulong=strtoul(buf, NULL, 10);
7268
7269 return RETURN_OK;
7270}
7271
7272// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7273INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7274{
7275 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7276 char ap_pin[16] = {0};
7277 char buf[MAX_BUF_SIZE] = {0};
7278 char config_file[MAX_BUF_SIZE] = {0};
7279 ULONG prev_pin = 0;
7280 struct params params;
7281
developer06a01d92022-09-07 16:32:39 +08007282 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7283 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7284 params.name = "ap_pin";
7285 params.value = ap_pin;
7286 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7287 wifi_hostapdWrite(config_file, &params, 1);
7288 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7290
7291 return RETURN_OK;
7292}
7293
7294// Output string is either Not configured or Configured, max 32 characters
7295INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7296{
developerd946fd62022-12-08 18:03:28 +08007297 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007298 char cmd[MAX_CMD_SIZE];
7299 char buf[MAX_BUF_SIZE]={0};
7300
developer5b398df2022-11-17 20:39:48 +08007301 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007302 return RETURN_ERR;
7303 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7304 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007305 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007306 return RETURN_ERR;
7307 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007308 _syscmd(cmd, buf, sizeof(buf));
7309
developer348e3d92022-09-13 14:48:41 +08007310 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007311 snprintf(output_string, 32, "Configured");
7312 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7313
7314 return RETURN_OK;
7315}
7316
7317// sets the WPS pin for this AP
7318INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7319{
developerd946fd62022-12-08 18:03:28 +08007320 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007321 char cmd[MAX_CMD_SIZE];
7322 char buf[MAX_BUF_SIZE]={0};
7323 BOOL enable;
7324
developer06a01d92022-09-07 16:32:39 +08007325 wifi_getApEnable(apIndex, &enable);
7326 if (!enable)
7327 return RETURN_ERR;
7328 wifi_getApWpsEnable(apIndex, &enable);
7329 if (!enable)
7330 return RETURN_ERR;
7331
developerac6f1142022-12-20 19:26:35 +08007332 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007333 return RETURN_ERR;
7334 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007335 _syscmd(cmd, buf, sizeof(buf));
7336 if((strstr(buf, "OK"))!=NULL)
7337 return RETURN_OK;
7338
7339 return RETURN_ERR;
7340}
7341
7342// This function is called when the WPS push button has been pressed for this AP
7343INT wifi_setApWpsButtonPush(INT apIndex)
7344{
7345 char cmd[MAX_CMD_SIZE];
7346 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007347 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007348 BOOL enable=FALSE;
7349
developer06a01d92022-09-07 16:32:39 +08007350 wifi_getApEnable(apIndex, &enable);
7351 if (!enable)
7352 return RETURN_ERR;
7353
7354 wifi_getApWpsEnable(apIndex, &enable);
7355 if (!enable)
7356 return RETURN_ERR;
7357
developerac6f1142022-12-20 19:26:35 +08007358 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007359 return RETURN_ERR;
7360
developer900e2b72023-05-23 10:23:48 +08007361 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 +08007362 _syscmd(cmd, buf, sizeof(buf));
7363
7364 if((strstr(buf, "OK"))!=NULL)
7365 return RETURN_OK;
7366 return RETURN_ERR;
7367}
7368
7369// cancels WPS mode for this AP
7370INT wifi_cancelApWPS(INT apIndex)
7371{
developerd946fd62022-12-08 18:03:28 +08007372 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007373 char cmd[MAX_CMD_SIZE];
7374 char buf[MAX_BUF_SIZE]={0};
7375
developerac6f1142022-12-20 19:26:35 +08007376 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007377 return RETURN_ERR;
7378 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007379 _syscmd(cmd,buf, sizeof(buf));
7380
7381 if((strstr(buf, "OK"))!=NULL)
7382 return RETURN_OK;
7383 return RETURN_ERR;
7384}
7385
7386//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7387//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7388INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7389{
developerd946fd62022-12-08 18:03:28 +08007390 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007391 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007392 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007393 char cmd[256] = {0}, buf[2048] = {0};
7394 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007395 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007396 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007397 wifi_associated_dev_t *dev=NULL;
7398
7399 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7400 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007401 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007402 return RETURN_ERR;
7403 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007404 _syscmd(cmd,buf,sizeof(buf));
7405 *output_array_size = atoi(buf);
7406
7407 if (*output_array_size <= 0)
7408 return RETURN_OK;
7409
7410 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7411 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007412 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007413 _syscmd(cmd,buf,sizeof(buf));
7414 f = fopen("/tmp/connected_devices.txt", "r");
7415 if (f==NULL)
7416 {
7417 *output_array_size=0;
7418 return RETURN_ERR;
7419 }
developer30423732022-12-01 16:17:49 +08007420 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007421 {
7422 param = strtok(line,"=");
7423 value = strtok(NULL,"=");
7424
7425 if( strcmp("flags",param) == 0 )
7426 {
7427 value[strlen(value)-1]='\0';
7428 if(strstr (value,"AUTHORIZED") != NULL )
7429 {
7430 dev[auth_temp].cli_AuthenticationState = 1;
7431 dev[auth_temp].cli_Active = 1;
7432 auth_temp++;
7433 read_flag=1;
7434 }
7435 }
7436 if(read_flag==1)
7437 {
7438 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7439 {
7440 value[strlen(value)-1]='\0';
7441 sscanf(value, "%x:%x:%x:%x:%x:%x",
7442 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7443 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7444 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7445 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7446 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7447 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7448 mac_temp++;
7449 read_flag=0;
7450 }
7451 }
7452 }
7453 *output_array_size = auth_temp;
7454 auth_temp=0;
7455 mac_temp=0;
7456 free(line);
7457 fclose(f);
7458 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7459 return RETURN_OK;
7460}
7461
7462#define MACADDRESS_SIZE 6
7463
7464INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7465{
7466 FILE *fp = NULL;
7467 char str[MAX_BUF_SIZE] = {0};
7468 int wificlientindex = 0 ;
7469 int count = 0;
7470 int signalstrength = 0;
7471 int arr[MACADDRESS_SIZE] = {0};
7472 unsigned char mac[MACADDRESS_SIZE] = {0};
7473 UINT wifi_count = 0;
7474 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7475 char pipeCmd[MAX_CMD_SIZE] = {0};
7476
7477 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7478 *output_array_size = 0;
7479 *associated_dev_array = NULL;
7480
7481 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7482 fp = popen(pipeCmd, "r");
7483 if (fp == NULL)
7484 {
7485 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7486 return RETURN_ERR;
7487 }
7488
7489 /* Read the output a line at a time - output it. */
7490 fgets(str, sizeof(str)-1, fp);
7491 wifi_count = (unsigned int) atoi ( str );
7492 *output_array_size = wifi_count;
7493 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7494 pclose(fp);
7495
7496 if(wifi_count == 0)
7497 {
7498 return RETURN_OK;
7499 }
7500 else
7501 {
7502 wifi_associated_dev3_t* temp = NULL;
7503 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7504 if(temp == NULL)
7505 {
7506 printf("Error Statement. Insufficient memory \n");
7507 return RETURN_ERR;
7508 }
7509
7510 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7511 system(pipeCmd);
7512 memset(pipeCmd,0,sizeof(pipeCmd));
7513 if(apIndex == 0)
7514 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7515 else if(apIndex == 1)
7516 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7517 system(pipeCmd);
7518
7519 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7520 if(fp == NULL)
7521 {
7522 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007523 free(temp);
developer06a01d92022-09-07 16:32:39 +08007524 return RETURN_ERR;
7525 }
7526 fclose(fp);
7527
developer30423732022-12-01 16:17:49 +08007528 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007529 fp = popen(pipeCmd, "r");
7530 if(fp)
7531 {
7532 for(count =0 ; count < wifi_count; count++)
7533 {
7534 fgets(str, MAX_BUF_SIZE, fp);
7535 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7536 {
7537 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7538 {
7539 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7540
7541 }
7542 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7543 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]);
7544 }
7545 temp[count].cli_AuthenticationState = 1; //TODO
7546 temp[count].cli_Active = 1; //TODO
7547 }
7548 pclose(fp);
7549 }
7550
developer30423732022-12-01 16:17:49 +08007551 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 +08007552 fp = popen(pipeCmd, "r");
7553 if(fp)
7554 {
7555 pclose(fp);
7556 }
7557 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7558 if(fp)
7559 {
7560 for(count =0 ; count < wifi_count ;count++)
7561 {
7562 fgets(str, MAX_BUF_SIZE, fp);
7563 signalstrength = atoi(str);
7564 temp[count].cli_SignalStrength = signalstrength;
7565 temp[count].cli_RSSI = signalstrength;
7566 temp[count].cli_SNR = signalstrength + 95;
7567 }
7568 pclose(fp);
7569 }
7570
7571
7572 if((apIndex == 0) || (apIndex == 4))
7573 {
7574 for(count =0 ; count < wifi_count ;count++)
7575 {
7576 strcpy(temp[count].cli_OperatingStandard,"g");
7577 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7578 }
7579
7580 //BytesSent
developer30423732022-12-01 16:17:49 +08007581 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 +08007582 fp = popen(pipeCmd, "r");
7583 if(fp)
7584 {
7585 pclose(fp);
7586 }
7587 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7588 if(fp)
7589 {
7590 for (count = 0; count < wifi_count; count++)
7591 {
7592 fgets(str, MAX_BUF_SIZE, fp);
7593 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7594 }
7595 pclose(fp);
7596 }
7597
7598 //BytesReceived
developer30423732022-12-01 16:17:49 +08007599 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 +08007600 fp = popen(pipeCmd, "r");
7601 if (fp)
7602 {
7603 pclose(fp);
7604 }
7605 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7606 if (fp)
7607 {
7608 for (count = 0; count < wifi_count; count++)
7609 {
7610 fgets(str, MAX_BUF_SIZE, fp);
7611 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7612 }
7613 pclose(fp);
7614 }
7615
7616 //PacketsSent
developer30423732022-12-01 16:17:49 +08007617 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 +08007618 fp = popen(pipeCmd, "r");
7619 if (fp)
7620 {
7621 pclose(fp);
7622 }
7623
7624 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7625 if (fp)
7626 {
7627 for (count = 0; count < wifi_count; count++)
7628 {
7629 fgets(str, MAX_BUF_SIZE, fp);
7630 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7631 }
7632 pclose(fp);
7633 }
7634
7635 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007636 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 +08007637 fp = popen(pipeCmd, "r");
7638 if (fp)
7639 {
7640 pclose(fp);
7641 }
7642 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7643 if (fp)
7644 {
7645 for (count = 0; count < wifi_count; count++)
7646 {
7647 fgets(str, MAX_BUF_SIZE, fp);
7648 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7649 }
7650 pclose(fp);
7651 }
7652
7653 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007654 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 +08007655 fp = popen(pipeCmd, "r");
7656 if (fp)
7657 {
7658 pclose(fp);
7659 }
7660 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7661 if (fp)
7662 {
7663 for (count = 0; count < wifi_count; count++)
7664 {
7665 fgets(str, MAX_BUF_SIZE, fp);
7666 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7667 }
7668 pclose(fp);
7669 }
7670
7671 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007672 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 +08007673 fp = popen(pipeCmd, "r");
7674 if (fp)
7675 {
7676 pclose(fp);
7677 }
7678 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7679 if (fp)
7680 {
7681 for (count = 0; count < wifi_count; count++)
7682 {
7683 fgets(str, MAX_BUF_SIZE, fp);
7684 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7685 }
7686 pclose(fp);
7687 }
7688
7689 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007690 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 +08007691 fp = popen(pipeCmd, "r");
7692 if (fp)
7693 {
7694 pclose(fp);
7695 }
7696 fp = popen("cat /tmp/Ass_Bitrate_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_LastDataDownlinkRate = strtoul(str, NULL, 10);
7703 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7704 }
7705 pclose(fp);
7706 }
7707
7708 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007709 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 +08007710 fp = popen(pipeCmd, "r");
7711 if (fp)
7712 {
7713 pclose(fp);
7714 }
7715 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7716 if (fp)
7717 {
7718 for (count = 0; count < wifi_count; count++)
7719 {
7720 fgets(str, MAX_BUF_SIZE, fp);
7721 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7722 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7723 }
7724 pclose(fp);
7725 }
7726
7727 }
7728 else if ((apIndex == 1) || (apIndex == 5))
7729 {
7730 for (count = 0; count < wifi_count; count++)
7731 {
7732 strcpy(temp[count].cli_OperatingStandard, "a");
7733 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7734 temp[count].cli_BytesSent = 0;
7735 temp[count].cli_BytesReceived = 0;
7736 temp[count].cli_LastDataUplinkRate = 0;
7737 temp[count].cli_LastDataDownlinkRate = 0;
7738 temp[count].cli_PacketsSent = 0;
7739 temp[count].cli_PacketsReceived = 0;
7740 temp[count].cli_ErrorsSent = 0;
7741 }
7742 }
7743
7744 for (count = 0; count < wifi_count; count++)
7745 {
7746 temp[count].cli_Retransmissions = 0;
7747 temp[count].cli_DataFramesSentAck = 0;
7748 temp[count].cli_DataFramesSentNoAck = 0;
7749 temp[count].cli_MinRSSI = 0;
7750 temp[count].cli_MaxRSSI = 0;
7751 strncpy(temp[count].cli_InterferenceSources, "", 64);
7752 memset(temp[count].cli_IPAddress, 0, 64);
7753 temp[count].cli_RetransCount = 0;
7754 temp[count].cli_FailedRetransCount = 0;
7755 temp[count].cli_RetryCount = 0;
7756 temp[count].cli_MultipleRetryCount = 0;
7757 }
7758 *associated_dev_array = temp;
7759 }
7760 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7761 return RETURN_OK;
7762}
7763
7764int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7765{
7766 FILE *fp = NULL;
7767 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7768 char cmd[MAX_CMD_SIZE];
7769 int count = 0;
7770
7771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7772 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7773 fp = popen(cmd,"r");
7774 if(fp == NULL)
7775 {
7776 printf("Failed to run command in Function %s\n",__FUNCTION__);
7777 return 0;
7778 }
7779 if(fgets(path, sizeof(path)-1, fp) != NULL)
7780 {
7781 for(count=0;path[count]!='\n';count++)
7782 status[count]=path[count];
7783 status[count]='\0';
7784 }
7785 strcpy(wifi_status,status);
7786 pclose(fp);
7787 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7788 return RETURN_OK;
7789}
7790
7791/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7792struct hostapd_sta_param {
7793 char key[50];
7794 char value[100];
7795}
7796
7797static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7798 int i = 0;
7799
7800 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7801 if (strncmp(params[i].key,key,50) == 0){
7802 return &params[i].value;
7803 }
7804 i++;
7805 }
7806 return NULL;
7807
7808} */
7809
7810static unsigned int count_occurences(const char *buf, const char *word)
7811{
7812 unsigned int n = 0;
7813 char *ptr = strstr(buf, word);
7814
7815 while (ptr++) {
7816 n++;
7817 ptr = strstr(ptr, word);
7818 }
7819
7820 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7821 return n;
7822}
7823
7824static const char *get_line_from_str_buf(const char *buf, char *line)
7825{
7826 int i;
7827 int n = strlen(buf);
7828
7829 for (i = 0; i < n; i++) {
7830 line[i] = buf[i];
7831 if (buf[i] == '\n') {
7832 line[i] = '\0';
7833 return &buf[i + 1];
7834 }
7835 }
7836
7837 return NULL;
7838}
7839
7840INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7841{
7842 unsigned int assoc_cnt = 0;
7843 char interface_name[50] = {0};
7844 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7845 char cmd[MAX_CMD_SIZE] = {'\0'};
7846 char line[256] = {'\0'};
7847 int i = 0;
7848 int ret = 0;
7849 const char *ptr = NULL;
7850 char *key = NULL;
7851 char *val = NULL;
7852 wifi_associated_dev3_t *temp = NULL;
7853 int rssi;
7854
7855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7856
7857 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7858 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7859 return RETURN_ERR;
7860 }
7861
7862 // Example filtered output of 'iw dev' command:
7863 // Station 0a:69:72:10:d2:fa (on wifi0)
7864 // signal avg:-67 [-71, -71] dBm
7865 // Station 28:c2:1f:25:5f:99 (on wifi0)
7866 // signal avg:-67 [-71, -70] dBm
7867 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7868 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7869 return RETURN_ERR;
7870 }
7871
7872 ret = _syscmd(cmd, buf, sizeof(buf));
7873 if (ret == RETURN_ERR) {
7874 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7875 return RETURN_ERR;
7876 }
7877
7878 *output_array_size = count_occurences(buf, "Station");
7879 if (*output_array_size == 0) return RETURN_OK;
7880
7881 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7882 if (temp == NULL) {
7883 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7884 return RETURN_ERR;
7885 }
7886 *associated_dev_array = temp;
7887
7888 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7889 ptr = get_line_from_str_buf(buf, line);
7890 i = -1;
7891 while (ptr) {
7892 if (strstr(line, "Station")) {
7893 i++;
7894 key = strtok(line, " ");
7895 val = strtok(NULL, " ");
7896 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7897 &temp[i].cli_MACAddress[0],
7898 &temp[i].cli_MACAddress[1],
7899 &temp[i].cli_MACAddress[2],
7900 &temp[i].cli_MACAddress[3],
7901 &temp[i].cli_MACAddress[4],
7902 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7903 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7904 free(*associated_dev_array);
7905 return RETURN_ERR;
7906 }
7907 }
7908 else if (i < 0) {
7909 ptr = get_line_from_str_buf(ptr, line);
7910 continue; // We didn't detect 'station' entry yet
7911 }
7912 else if (strstr(line, "signal avg")) {
7913 key = strtok(line, ":");
7914 val = strtok(NULL, " ");
7915 if (sscanf(val, "%d", &rssi) <= 0 ) {
7916 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7917 free(*associated_dev_array);
7918 return RETURN_ERR;
7919 }
7920 temp[i].cli_RSSI = rssi;
7921 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7922 }
7923 // Here other fields can be parsed if added to filter of 'iw dev' command
7924
7925 ptr = get_line_from_str_buf(ptr, line);
7926 };
7927
7928 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7929
7930 return RETURN_OK;
7931}
7932
7933#if 0
7934//To-do
7935INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7936{
7937 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7938
7939 //Using different approach to get required WiFi Parameters from system available commands
7940#if 0
7941 FILE *f;
7942 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7943 char cmd[256], buf[2048];
7944 char *param , *value, *line=NULL;
7945 size_t len = 0;
7946 ssize_t nread;
7947 wifi_associated_dev3_t *dev=NULL;
7948 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007949 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007950 _syscmd(cmd,buf,sizeof(buf));
7951 *output_array_size = atoi(buf);
7952
7953 if (*output_array_size <= 0)
7954 return RETURN_OK;
7955
7956 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7957 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007958 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007959 _syscmd(cmd,buf,sizeof(buf));
7960 f = fopen("/tmp/connected_devices.txt", "r");
7961 if (f==NULL)
7962 {
7963 *output_array_size=0;
7964 return RETURN_ERR;
7965 }
7966 while ((nread = getline(&line, &len, f)) != -1)
7967 {
7968 param = strtok(line,"=");
7969 value = strtok(NULL,"=");
7970
7971 if( strcmp("flags",param) == 0 )
7972 {
7973 value[strlen(value)-1]='\0';
7974 if(strstr (value,"AUTHORIZED") != NULL )
7975 {
7976 dev[auth_temp].cli_AuthenticationState = 1;
7977 dev[auth_temp].cli_Active = 1;
7978 auth_temp++;
7979 read_flag=1;
7980 }
7981 }
7982 if(read_flag==1)
7983 {
7984 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7985 {
7986 value[strlen(value)-1]='\0';
7987 sscanf(value, "%x:%x:%x:%x:%x:%x",
7988 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7989 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7990 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7991 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7992 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7993 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7994
7995 }
7996 else if( strcmp("rx_packets",param) == 0 )
7997 {
7998 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7999 }
8000
8001 else if( strcmp("tx_packets",param) == 0 )
8002 {
8003 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8004 }
8005
8006 else if( strcmp("rx_bytes",param) == 0 )
8007 {
8008 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8009 }
8010
8011 else if( strcmp("tx_bytes",param) == 0 )
8012 {
8013 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8014 mac_temp++;
8015 read_flag=0;
8016 }
8017 }
8018 }
8019
8020 *output_array_size = auth_temp;
8021 auth_temp=0;
8022 mac_temp=0;
8023 free(line);
8024 fclose(f);
8025#endif
8026 char interface_name[MAX_BUF_SIZE] = {0};
8027 char wifi_status[MAX_BUF_SIZE] = {0};
8028 char hostapdconf[MAX_BUF_SIZE] = {0};
8029
8030 wifi_associated_dev3_t *dev_array = NULL;
8031 ULONG wifi_count = 0;
8032
8033 *associated_dev_array = NULL;
8034 *output_array_size = 0;
8035
8036 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8037 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8038 {
8039 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8040
developerac6f1142022-12-20 19:26:35 +08008041 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008042
8043 if(strlen(interface_name) > 1)
8044 {
8045 wifihal_interfacestatus(wifi_status,interface_name);
8046 if(strcmp(wifi_status,"RUNNING") == 0)
8047 {
8048 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8049
8050 *associated_dev_array = dev_array;
8051 *output_array_size = wifi_count;
8052 }
8053 else
8054 {
8055 *associated_dev_array = NULL;
8056 }
8057 }
8058 }
8059
8060 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8061 return RETURN_OK;
8062}
8063#endif
8064
8065/* getIPAddress function */
8066/**
8067* @description Returning IpAddress of the Matched String
8068*
8069* @param
8070* @str Having MacAddress
8071* @ipaddr Having ipaddr
8072* @return The status of the operation
8073* @retval RETURN_OK if successful
8074* @retval RETURN_ERR if any error is detected
8075*
8076*/
8077
8078INT getIPAddress(char *str,char *ipaddr)
8079{
8080 FILE *fp = NULL;
8081 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8082 int LeaseTime = 0,ret = 0;
8083 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8084 {
8085 return RETURN_ERR;
8086 }
8087
8088 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8089 {
8090 /*
8091 Sample:sss
8092 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8093 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8094 */
8095 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008096 &(LeaseTime),
8097 phyAddr,
8098 ipAddr,
8099 hostName
8100 );
developer06a01d92022-09-07 16:32:39 +08008101 if(ret != 4)
8102 continue;
8103 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008104 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008105 }
developerd946fd62022-12-08 18:03:28 +08008106 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008107 return RETURN_OK;
8108}
8109
8110/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8111/**
8112* @description Returning Inactive wireless connected clients informations
8113*
8114* @param
8115* @filename Holding private_wifi 2g/5g content files
8116* @associated_dev_array Having inactiv wireless clients informations
8117* @output_array_size Returning Inactive wireless counts
8118* @return The status of the operation
8119* @retval RETURN_OK if successful
8120* @retval RETURN_ERR if any error is detected
8121*
8122*/
8123
8124INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8125{
8126 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8127 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8128 FILE *fp = NULL;
8129 int arr[MACADDRESS_SIZE] = {0};
8130 unsigned char mac[MACADDRESS_SIZE] = {0};
8131 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8132 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8133 fp = popen(buf,"r");
8134 if(fp == NULL)
8135 return RETURN_ERR;
8136 else
8137 {
8138 fgets(path,sizeof(path),fp);
8139 maccount = atoi(path);
8140 }
8141 pclose(fp);
8142 *output_array_size = maccount;
8143 wifi_associated_dev3_t* temp = NULL;
8144 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8145 *associated_dev_array = temp;
8146 if(temp == NULL)
8147 {
8148 printf("Error Statement. Insufficient memory \n");
8149 return RETURN_ERR;
8150 }
8151 memset(buf,0,sizeof(buf));
8152 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8153 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008154 if (fp == NULL) {
8155 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8156 return RETURN_ERR;
8157 }
developer06a01d92022-09-07 16:32:39 +08008158 for(count = 0; count < maccount ; count++)
8159 {
8160 fgets(path,sizeof(path),fp);
8161 for(i = 0; path[i]!='\n';i++)
8162 str[i]=path[i];
8163 str[i]='\0';
8164 getIPAddress(str,ipaddr);
8165 memset(buf,0,sizeof(buf));
8166 if(strlen(ipaddr) > 0)
8167 {
8168 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8169 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8170 {
8171 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8172 {
8173 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8174 {
8175 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8176
8177 }
8178 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8179 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]);
8180 }
8181 temp[count].cli_AuthenticationState = 0; //TODO
8182 temp[count].cli_Active = 0; //TODO
8183 temp[count].cli_SignalStrength = 0;
8184 }
8185 else //Active wireless clients info
8186 {
8187 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8188 {
8189 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8190 {
8191 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8192
8193 }
8194 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8195 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]);
8196 }
8197 temp[count].cli_Active = 1;
8198 }
8199 }
8200 memset(ipaddr,0,sizeof(ipaddr));
8201 }
8202 pclose(fp);
8203 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8204 return RETURN_OK;
8205}
8206//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8207//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8208//To get Band Steering Capability
8209INT wifi_getBandSteeringCapability(BOOL *support)
8210{
8211 *support = FALSE;
8212 return RETURN_OK;
8213}
8214
8215
8216//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8217//To get Band Steering enable status
8218INT wifi_getBandSteeringEnable(BOOL *enable)
8219{
8220 *enable = FALSE;
8221 return RETURN_OK;
8222}
8223
8224//To turn on/off Band steering
8225INT wifi_setBandSteeringEnable(BOOL enable)
8226{
8227 return RETURN_OK;
8228}
8229
8230//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8231//To get Band Steering AP group
8232INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8233{
8234 if (NULL == output_ApGroup)
8235 return RETURN_ERR;
8236
8237 strcpy(output_ApGroup, "1,2");
8238 return RETURN_OK;
8239}
8240
8241//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8242//to set and read the band steering BandUtilizationThreshold parameters
8243INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8244{
8245 return RETURN_ERR;
8246}
8247
8248INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8249{
8250 return RETURN_ERR;
8251}
8252
8253//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8254//to set and read the band steering RSSIThreshold parameters
8255INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8256{
8257 return RETURN_ERR;
8258}
8259
8260INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8261{
8262 return RETURN_ERR;
8263}
8264
8265
8266//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8267//to set and read the band steering physical modulation rate threshold parameters
8268INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8269{
8270 //If chip is not support, return -1
8271 return RETURN_ERR;
8272}
8273
8274INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8275{
8276 //If chip is not support, return -1
8277 return RETURN_ERR;
8278}
8279
8280//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8281//to set and read the inactivity time (in seconds) for steering under overload condition
8282INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8283{
8284 return RETURN_ERR;
8285}
8286
8287INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8288{
8289 return RETURN_ERR;
8290}
8291
8292//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8293//to set and read the inactivity time (in seconds) for steering under Idle condition
8294INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8295{
8296 return RETURN_ERR;
8297}
8298
8299INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8300{
8301 return RETURN_ERR;
8302}
8303
8304//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8305//pClientMAC[64]
8306//pSourceSSIDIndex[64]
8307//pDestSSIDIndex[64]
8308//pSteeringReason[256]
8309INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8310{
8311 //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
8312 *pSteeringTime=time(NULL);
8313 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8314 return RETURN_OK;
8315}
8316
8317INT wifi_ifConfigDown(INT apIndex)
8318{
8319 INT status = RETURN_OK;
8320 char cmd[64];
8321
8322 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8323 printf("%s: %s\n", __func__, cmd);
8324 system(cmd);
8325
8326 return status;
8327}
8328
8329INT wifi_ifConfigUp(INT apIndex)
8330{
developerd946fd62022-12-08 18:03:28 +08008331 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008332 char cmd[128];
8333 char buf[1024];
8334
developerac6f1142022-12-20 19:26:35 +08008335 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008336 return RETURN_ERR;
8337 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008338 _syscmd(cmd, buf, sizeof(buf));
8339 return 0;
8340}
8341
8342//>> Deprecated. Replace with wifi_applyRadioSettings
8343INT wifi_pushBridgeInfo(INT apIndex)
8344{
developerd946fd62022-12-08 18:03:28 +08008345 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008346 char ip[32] = {0};
8347 char subnet[32] = {0};
8348 char bridge[32] = {0};
8349 int vlanId = 0;
8350 char cmd[128] = {0};
8351 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008352
8353 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8354 wifi_getApVlanID(apIndex,&vlanId);
8355
developerac6f1142022-12-20 19:26:35 +08008356 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008357 return RETURN_ERR;
8358 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008359 _syscmd(cmd,buf, sizeof(buf));
8360
8361 return 0;
8362}
8363
8364INT wifi_pushChannel(INT radioIndex, UINT channel)
8365{
developerd946fd62022-12-08 18:03:28 +08008366 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008367 char cmd[128];
8368 char buf[1024];
8369 int apIndex;
8370
8371 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008372 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008373 return RETURN_ERR;
8374 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008375 _syscmd(cmd,buf, sizeof(buf));
8376
8377 return 0;
8378}
8379
8380INT wifi_pushChannelMode(INT radioIndex)
8381{
8382 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8383 return RETURN_ERR;
8384}
8385
8386INT wifi_pushDefaultValues(INT radioIndex)
8387{
8388 //Apply Comcast specified default radio settings instantly
8389 //AMPDU=1
8390 //AMPDUFrames=32
8391 //AMPDULim=50000
8392 //txqueuelen=1000
8393
8394 return RETURN_ERR;
8395}
8396
8397INT wifi_pushTxChainMask(INT radioIndex)
8398{
8399 //Apply default TxChainMask instantly
8400 return RETURN_ERR;
8401}
8402
8403INT wifi_pushRxChainMask(INT radioIndex)
8404{
8405 //Apply default RxChainMask instantly
8406 return RETURN_ERR;
8407}
8408
8409INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8410{
8411 INT status;
8412
8413 status = wifi_setSSIDName(apIndex,ssid);
8414 wifi_setApEnable(apIndex,FALSE);
8415 wifi_setApEnable(apIndex,TRUE);
8416
8417 return status;
8418}
8419
8420INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8421{
8422 //Apply default Ssid Advertisement instantly
8423 return RETURN_ERR;
8424}
8425
8426INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8427{
8428 INT status = RETURN_ERR;
8429 *output = 0;
8430 return RETURN_ERR;
8431}
8432
8433INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8434{
8435 return RETURN_OK;
8436}
8437
8438INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8439{
8440 return RETURN_OK;
8441}
8442
8443//To-do
8444INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8445{
developereb199ae2022-09-13 14:04:27 +08008446 char output[16]={'\0'};
8447 char config_file[MAX_BUF_SIZE] = {0};
8448
8449 if (!output_string)
8450 return RETURN_ERR;
8451
8452 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8453 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8454
8455 if (strlen(output) == 0)
8456 snprintf(output_string, 64, "Disabled");
8457 else if (strncmp(output, "0", 1) == 0)
8458 snprintf(output_string, 64, "Disabled");
8459 else if (strncmp(output, "1", 1) == 0)
8460 snprintf(output_string, 64, "Optional");
8461 else if (strncmp(output, "2", 1) == 0)
8462 snprintf(output_string, 64, "Required");
8463 else {
8464 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8465 return RETURN_ERR;
8466 }
8467
8468 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008469 return RETURN_OK;
8470}
8471INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8472{
developereb199ae2022-09-13 14:04:27 +08008473 char str[MAX_BUF_SIZE]={'\0'};
8474 char cmd[MAX_CMD_SIZE]={'\0'};
8475 struct params params;
8476 char config_file[MAX_BUF_SIZE] = {0};
8477
8478 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8479 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8480 return RETURN_ERR;
8481
8482 params.name = "ieee80211w";
8483 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8484 params.value = "0";
8485 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8486 params.value = "1";
8487 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8488 params.value = "2";
8489 else{
8490 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8491 return RETURN_ERR;
8492 }
8493 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8494 wifi_hostapdWrite(config_file, &params, 1);
8495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008496 return RETURN_OK;
8497}
8498INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8499{
8500 char output[16]={'\0'};
8501 char config_file[MAX_BUF_SIZE] = {0};
8502
8503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8504 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8505 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8506
8507 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8508 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8509
8510 return RETURN_OK;
8511}
8512
8513INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8514{
8515 return RETURN_OK;
8516}
8517
8518INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8519{
8520 return RETURN_OK;
8521}
8522
8523INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8524{
8525 return RETURN_OK;
8526}
8527
8528INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8529{
8530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8531 char config_file[MAX_BUF_SIZE] = {0};
8532
8533 if (NULL == output)
8534 return RETURN_ERR;
8535 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8536 wifi_hostapdRead(config_file,"hw_mode",output,64);
8537
8538 if(strcmp(output,"b")==0)
8539 sprintf(output, "%s", "1,2,5.5,11");
8540 else if (strcmp(output,"a")==0)
8541 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8542 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8543 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8544
8545 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8546 return RETURN_OK;
8547}
8548
8549INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8550{
8551 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8552 char *temp;
8553 char temp_output[128];
8554 char temp_TransmitRates[128];
8555 char config_file[MAX_BUF_SIZE] = {0};
8556
8557 if (NULL == output)
8558 return RETURN_ERR;
8559
8560 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8561 wifi_hostapdRead(config_file,"supported_rates",output,64);
8562
developer5b398df2022-11-17 20:39:48 +08008563 if (strlen(output) == 0) {
8564 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8565 return RETURN_OK;
8566 }
developer06a01d92022-09-07 16:32:39 +08008567 strcpy(temp_TransmitRates,output);
8568 strcpy(temp_output,"");
8569 temp = strtok(temp_TransmitRates," ");
8570 while(temp!=NULL)
8571 {
8572 temp[strlen(temp)-1]=0;
8573 if((temp[0]=='5') && (temp[1]=='\0'))
8574 {
8575 temp="5.5";
8576 }
8577 strcat(temp_output,temp);
8578 temp = strtok(NULL," ");
8579 if(temp!=NULL)
8580 {
8581 strcat(temp_output,",");
8582 }
8583 }
8584 strcpy(output,temp_output);
8585 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8586
8587 return RETURN_OK;
8588}
8589
8590INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8591{
8592 return RETURN_OK;
8593}
8594
8595
8596INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8597{
8598 int i=0;
8599 char *temp;
developeref938762022-10-19 17:21:01 +08008600 char temp1[128] = {0};
8601 char temp_output[128] = {0};
8602 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008603 struct params params={'\0'};
8604 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008605 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008606
8607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8608 if(NULL == output)
8609 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008610 strcpy(temp_TransmitRates,output);
8611
8612 for(i=0;i<strlen(temp_TransmitRates);i++)
8613 {
developeref938762022-10-19 17:21:01 +08008614 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008615 {
8616 continue;
8617 }
8618 else
8619 {
8620 return RETURN_ERR;
8621 }
8622 }
8623 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008624 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008625 while(temp!=NULL)
8626 {
8627 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008628 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008629 {
developeref938762022-10-19 17:21:01 +08008630 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008631 {
8632 return RETURN_ERR;
8633 }
8634 }
8635
8636 if(strcmp(temp,"5.5")==0)
8637 {
8638 strcpy(temp1,"55");
8639 }
8640 else
8641 {
8642 strcat(temp1,"0");
8643 }
8644 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008645 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008646 if(temp!=NULL)
8647 {
8648 strcat(temp_output," ");
8649 }
8650 }
8651 strcpy(output,temp_output);
8652
developer06a01d92022-09-07 16:32:39 +08008653 params.name = "supported_rates";
8654 params.value = output;
8655
8656 wifi_dbg_printf("\n%s:",__func__);
8657 wifi_dbg_printf("params.value=%s\n",params.value);
8658 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8659 wifi_hostapdWrite(config_file,&params,1);
8660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8661
8662 return RETURN_OK;
8663}
8664
8665
8666static char *sncopy(char *dst, int dst_sz, const char *src)
8667{
8668 if (src && dst && dst_sz > 0) {
8669 strncpy(dst, src, dst_sz);
8670 dst[dst_sz - 1] = '\0';
8671 }
8672 return dst;
8673}
8674
8675static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8676{
8677 if (0 == strcmp(ht_mode, "HT40") ||
8678 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008679 0 == strcmp(ht_mode, "HT160") ||
8680 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008681 switch (channel) {
developer9a520b12023-09-21 16:01:43 +08008682 case 0 ... 7:
developer06a01d92022-09-07 16:32:39 +08008683 case 36:
8684 case 44:
8685 case 52:
8686 case 60:
8687 case 100:
8688 case 108:
8689 case 116:
8690 case 124:
8691 case 132:
8692 case 140:
8693 case 149:
8694 case 157:
8695 return 1;
8696 case 8 ... 13:
8697 case 40:
8698 case 48:
8699 case 56:
8700 case 64:
8701 case 104:
8702 case 112:
8703 case 120:
8704 case 128:
8705 case 136:
8706 case 144:
8707 case 153:
8708 case 161:
8709 return -1;
8710 default:
8711 return -EINVAL;
8712 }
8713 }
8714
8715 return -EINVAL;
8716}
8717
developerb7593de2022-10-18 09:51:57 +08008718static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8719{
8720 int idx = channel%8;
8721 if (0 == strcmp(ht_mode, "HT40") ||
8722 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008723 0 == strcmp(ht_mode, "HT160") ||
8724 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008725 switch (idx) {
8726 case 1:
8727 return 1;
8728 case 5:
8729 return -1;
8730 default:
8731 return -EINVAL;
8732 }
8733 }
8734
8735 return -EINVAL;
8736}
developer06a01d92022-09-07 16:32:39 +08008737static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8738{
8739 if (NULL == hw_mode) return;
8740
8741 if (0 == strcmp(hw_mode, "ac"))
8742 sncopy(bw_mode, bw_mode_len, "ht vht");
8743
8744 if (0 == strcmp(hw_mode, "n"))
8745 sncopy(bw_mode, bw_mode_len, "ht");
8746
8747 return;
8748}
8749
8750static int util_chan_to_freq(int chan)
8751{
8752 if (chan == 14)
8753 return 2484;
8754 else if (chan < 14)
8755 return 2407 + chan * 5;
8756 else if (chan >= 182 && chan <= 196)
8757 return 4000 + chan * 5;
8758 else
8759 return 5000 + chan * 5;
8760 return 0;
8761}
8762
developerb7593de2022-10-18 09:51:57 +08008763static int util_6G_chan_to_freq(int chan)
8764{
8765 if (chan)
8766 return 5950 + chan * 5;
8767 else
8768 return 0;
8769
8770}
developer06a01d92022-09-07 16:32:39 +08008771const int *util_unii_5g_chan2list(int chan, int width)
8772{
8773 static const int lists[] = {
8774 // <width>, <chan1>, <chan2>..., 0,
8775 20, 36, 0,
8776 20, 40, 0,
8777 20, 44, 0,
8778 20, 48, 0,
8779 20, 52, 0,
8780 20, 56, 0,
8781 20, 60, 0,
8782 20, 64, 0,
8783 20, 100, 0,
8784 20, 104, 0,
8785 20, 108, 0,
8786 20, 112, 0,
8787 20, 116, 0,
8788 20, 120, 0,
8789 20, 124, 0,
8790 20, 128, 0,
8791 20, 132, 0,
8792 20, 136, 0,
8793 20, 140, 0,
8794 20, 144, 0,
8795 20, 149, 0,
8796 20, 153, 0,
8797 20, 157, 0,
8798 20, 161, 0,
8799 20, 165, 0,
8800 40, 36, 40, 0,
8801 40, 44, 48, 0,
8802 40, 52, 56, 0,
8803 40, 60, 64, 0,
8804 40, 100, 104, 0,
8805 40, 108, 112, 0,
8806 40, 116, 120, 0,
8807 40, 124, 128, 0,
8808 40, 132, 136, 0,
8809 40, 140, 144, 0,
8810 40, 149, 153, 0,
8811 40, 157, 161, 0,
8812 80, 36, 40, 44, 48, 0,
8813 80, 52, 56, 60, 64, 0,
8814 80, 100, 104, 108, 112, 0,
8815 80, 116, 120, 124, 128, 0,
8816 80, 132, 136, 140, 144, 0,
8817 80, 149, 153, 157, 161, 0,
8818 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8819 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8820 -1 // final delimiter
8821 };
8822 const int *start;
8823 const int *p;
8824
8825 for (p = lists; *p != -1; p++) {
8826 if (*p == width) {
8827 for (start = ++p; *p != 0; p++) {
8828 if (*p == chan)
8829 return start;
8830 }
8831 }
8832 // move to the end of channel list of given width
8833 while (*p != 0) {
8834 p++;
8835 }
8836 }
8837
8838 return NULL;
8839}
8840
8841static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8842{
8843 if (NULL == ht_mode)
8844 return 0;
8845
8846 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8847 const int *chans = util_unii_5g_chan2list(channel, width);
8848 int sum = 0;
8849 int cnt = 0;
8850
8851 if (NULL == chans)
8852 return 0;
8853
8854 while (*chans) {
8855 sum += *chans;
8856 cnt++;
8857 chans++;
8858 }
developer30423732022-12-01 16:17:49 +08008859 if (cnt == 0)
8860 return 0;
developer06a01d92022-09-07 16:32:39 +08008861 return sum / cnt;
8862}
8863
developerb7593de2022-10-18 09:51:57 +08008864static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8865{
8866 if (NULL == ht_mode)
8867 return 0;
8868
8869 int width = strtol((ht_mode + 2), NULL, 10);
8870
8871 int idx = 0 ;
8872 int centerchan = 0;
8873 int chan_ofs = 1;
8874
8875 if (width == 40){
8876 idx = ((channel/4) + chan_ofs)%2;
8877 switch (idx) {
8878 case 0:
8879 centerchan = (channel - 2);
8880 break;
8881 case 1:
8882 centerchan = (channel + 2);
8883 break;
8884 default:
8885 return -EINVAL;
8886 }
8887 }else if (width == 80){
8888 idx = ((channel/4) + chan_ofs)%4;
8889 switch (idx) {
8890 case 0:
8891 centerchan = (channel - 6);
8892 break;
8893 case 1:
8894 centerchan = (channel + 6);
8895 break;
8896 case 2:
8897 centerchan = (channel + 2);
8898 break;
8899 case 3:
8900 centerchan = (channel - 2);
8901 break;
8902 default:
8903 return -EINVAL;
8904 }
8905 }else if (width == 160){
8906 switch (channel) {
8907 case 1 ... 29:
8908 centerchan = 15;
8909 break;
8910 case 33 ... 61:
8911 centerchan = 47;
8912 break;
8913 case 65 ... 93:
8914 centerchan = 79;
8915 break;
8916 case 97 ... 125:
8917 centerchan = 111;
8918 break;
8919 case 129 ... 157:
8920 centerchan = 143;
8921 break;
8922 case 161 ... 189:
8923 centerchan = 175;
8924 break;
8925 case 193 ... 221:
8926 centerchan = 207;
8927 break;
8928 default:
8929 return -EINVAL;
8930 }
developer7c4cd202023-03-01 10:56:29 +08008931 }else if (width == 320){
8932 switch (channel) {
8933 case 1 ... 29:
8934 centerchan = 31;
8935 break;
8936 case 33 ... 93:
8937 centerchan = 63;
8938 break;
8939 case 97 ... 157:
8940 centerchan = 127;
8941 break;
8942 case 161 ... 221:
8943 centerchan = 191;
8944 break;
8945 default:
8946 return -EINVAL;
8947 }
developerb7593de2022-10-18 09:51:57 +08008948 }
8949 return centerchan;
8950}
developer06a01d92022-09-07 16:32:39 +08008951static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8952{
8953 BOOL onlyG, onlyN, onlyA;
8954 CHAR tmp[64];
8955 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8956 if (ret == RETURN_OK) {
8957 sncopy(hw_mode, hw_mode_size, tmp);
8958 }
8959 return ret;
8960}
8961
8962INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8963{
8964 // Sample commands:
8965 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8966 // hostapd_cli -i wifi0 chan_switch 30 2437
8967 char cmd[MAX_CMD_SIZE] = {0};
8968 char buf[MAX_BUF_SIZE] = {0};
8969 int freq = 0, ret = 0;
8970 char center_freq1_str[32] = ""; // center_freq1=%d
8971 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8972 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8973 char hw_mode[16] = ""; // n|ac
8974 char bw_mode[16] = ""; // ht|ht vht
8975 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008976 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008977 int sec_chan_offset;
8978 int width;
developer4fb0b922022-09-30 14:29:09 +08008979 char config_file[64] = {0};
8980 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08008981 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08008982 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008983 wifi_band band = band_invalid;
8984 int center_chan = 0;
8985 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008986
developer4fb0b922022-09-30 14:29:09 +08008987 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008988
developerac6f1142022-12-20 19:26:35 +08008989 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008990 return RETURN_ERR;
8991
developer06a01d92022-09-07 16:32:39 +08008992 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8993
developerb7593de2022-10-18 09:51:57 +08008994 band = wifi_index_to_band(radioIndex);
8995
developer5884e982022-10-06 10:52:50 +08008996 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008997
8998 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008999 if (channel){
developerb7593de2022-10-18 09:51:57 +08009000 if (band == band_6){
9001 freq = util_6G_chan_to_freq(channel);
9002 }else{
9003 freq = util_chan_to_freq(channel);
9004 }
developer7c4cd202023-03-01 10:56:29 +08009005 if (width == 320) {
9006 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
9007 setEHT320 = TRUE;
9008 }
developer5884e982022-10-06 10:52:50 +08009009 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08009010
developer5884e982022-10-06 10:52:50 +08009011 // Provide bandwith if specified
9012 if (channel_width_MHz > 20) {
9013 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9014 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9015 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08009016
developer5884e982022-10-06 10:52:50 +08009017 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9018 }else if (channel_width_MHz == 20){
9019 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9020 }
developer06a01d92022-09-07 16:32:39 +08009021
developerb7593de2022-10-18 09:51:57 +08009022
developer5884e982022-10-06 10:52:50 +08009023 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08009024 if (band == band_6){
9025 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9026 if(center_chan){
9027 center_freq1 = util_6G_chan_to_freq(center_chan);
9028 }
9029 }else{
9030 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9031 if(center_chan){
9032 center_freq1 = util_chan_to_freq(center_chan);
9033 }
developer5884e982022-10-06 10:52:50 +08009034 }
developerb7593de2022-10-18 09:51:57 +08009035
9036 if (center_freq1)
9037 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9038
9039 }
9040
9041 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9042 if (band == band_6){
9043 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9044 }else{
9045 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009046 }
developerb7593de2022-10-18 09:51:57 +08009047 if (sec_chan_offset != -EINVAL)
9048 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009049
developer5884e982022-10-06 10:52:50 +08009050 // Only the first AP, other are hanging on the same radio
9051 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009052 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9053 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009054 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9055 wifi_dbg_printf("execute: '%s'\n", cmd);
9056 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009057 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009058
developer5884e982022-10-06 10:52:50 +08009059 ret = wifi_setRadioChannel(radioIndex, channel);
9060 if (ret != RETURN_OK) {
9061 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9062 return RETURN_ERR;
9063 }
9064
9065 if (sec_chan_offset == 1) ext_str = "Above";
9066 else if (sec_chan_offset == -1) ext_str = "Below";
9067
9068 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009069
developer5884e982022-10-06 10:52:50 +08009070 } else {
9071 if (channel_width_MHz > 20)
9072 ext_str = "Above";
9073 }
developer4fb0b922022-09-30 14:29:09 +08009074
developer06a01d92022-09-07 16:32:39 +08009075 char mhz_str[16];
9076 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009077 if (setEHT320 == TRUE)
9078 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9079 else
9080 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009081
developer57fa24a2023-03-15 17:25:07 +08009082 writeBandWidth(radioIndex, mhz_str);
9083 if (band == band_2_4 || band == band_5) {
9084 if (width == 20)
9085 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9086 else
9087 wifi_setRadioExtChannel(radioIndex, ext_str);
9088 }
developer06a01d92022-09-07 16:32:39 +08009089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9090
9091 return RETURN_OK;
9092}
9093
9094INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9095{
developer615510b2022-09-27 10:14:35 +08009096 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009097 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009098 char cmd[256]={0};
9099 char buf[128]={0};
9100 char file_name[32] = {0};
9101 char filter_SSID[32] = {0};
9102 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009103 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009104 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009105 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009106 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009107 size_t len=0;
9108 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009109 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009110 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009111 bool filter_enable = false;
9112 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009113 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009114
developer615510b2022-09-27 10:14:35 +08009115 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009116
developer615510b2022-09-27 10:14:35 +08009117 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9118 f = fopen(file_name, "r");
9119 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009120 fgets(buf, sizeof(file_name), f);
9121 if ((strncmp(buf, "0", 1)) != 0) {
9122 fgets(filter_SSID, sizeof(file_name), f);
9123 if (strlen(filter_SSID) != 0)
9124 filter_enable = true;
9125 }
developer615510b2022-09-27 10:14:35 +08009126 fclose(f);
9127 }
9128
developerac6f1142022-12-20 19:26:35 +08009129 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009130 return RETURN_ERR;
9131
developer033b37b2022-10-18 11:27:46 +08009132 phyId = radio_index_to_phy(radio_index);
9133
9134 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009135 _syscmd(cmd, buf, sizeof(buf));
9136 channels_num = strtol(buf, NULL, 10);
9137
developerd946fd62022-12-08 18:03:28 +08009138 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9139 // 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 +08009140 fprintf(stderr, "cmd: %s\n", cmd);
9141 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009142 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9143 return RETURN_ERR;
9144 }
developer5550e242022-09-30 09:59:32 +08009145
9146 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9147 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9148
developer615510b2022-09-27 10:14:35 +08009149 ret = fgets(line, sizeof(line), f);
9150 while (ret != NULL) {
9151 if(strstr(line, "BSS") != NULL) { // new neighbor info
9152 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9153 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9154 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9155
9156 if (!filter_BSS) {
9157 index++;
9158 wifi_neighbor_ap2_t *tmp;
9159 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9160 if (tmp == NULL) { // no more memory to use
9161 index--;
9162 wifi_dbg_printf("%s: realloc failed\n", __func__);
9163 break;
9164 }
9165 scan_array = tmp;
9166 }
9167 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009168
developer615510b2022-09-27 10:14:35 +08009169 filter_BSS = false;
9170 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9171 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9172 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9173 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9174 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009175 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009176 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009177
developer615510b2022-09-27 10:14:35 +08009178 if (freq >= 2412 && freq <= 2484) {
9179 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9180 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9181 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9182 }
9183 else if (freq >= 5160 && freq <= 5805) {
9184 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9185 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9186 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9187 }
developer06a01d92022-09-07 16:32:39 +08009188
developer615510b2022-09-27 10:14:35 +08009189 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009190 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009191 for (int i = 0; i < channels_num; i++) {
9192 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9193 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9194 break;
9195 }
9196 }
developer06a01d92022-09-07 16:32:39 +08009197 }
developer615510b2022-09-27 10:14:35 +08009198 } else if (strstr(line, "beacon interval") != NULL) {
9199 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9200 } else if (strstr(line, "signal") != NULL) {
9201 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9202 } else if (strstr(line,"SSID") != NULL) {
9203 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9204 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9205 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009206 }
developer615510b2022-09-27 10:14:35 +08009207 } else if (strstr(line, "Supported rates") != NULL) {
9208 char SRate[80] = {0}, *tmp = NULL;
9209 memset(buf, 0, sizeof(buf));
9210 strcpy(SRate, line);
9211 tmp = strtok(SRate, ":");
9212 tmp = strtok(NULL, ":");
9213 strcpy(buf, tmp);
9214 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009215
developer615510b2022-09-27 10:14:35 +08009216 tmp = strtok(buf, " \n");
9217 while (tmp != NULL) {
9218 strcat(SRate, tmp);
9219 if (SRate[strlen(SRate) - 1] == '*') {
9220 SRate[strlen(SRate) - 1] = '\0';
9221 }
9222 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009223
developer615510b2022-09-27 10:14:35 +08009224 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009225 }
developer615510b2022-09-27 10:14:35 +08009226 SRate[strlen(SRate) - 1] = '\0';
9227 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9228 } else if (strstr(line, "DTIM") != NULL) {
9229 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9230 } else if (strstr(line, "VHT capabilities") != NULL) {
9231 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9232 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9233 } else if (strstr(line, "HT capabilities") != NULL) {
9234 strcat(scan_array[index].ap_SupportedStandards, ",n");
9235 strcpy(scan_array[index].ap_OperatingStandards, "n");
9236 } else if (strstr(line, "VHT operation") != NULL) {
9237 ret = fgets(line, sizeof(line), f);
9238 sscanf(line," * channel width: %d", &vht_channel_width);
9239 if(vht_channel_width == 1) {
9240 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9241 } else {
9242 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9243 }
9244 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9245 continue;
9246 } else if (strstr(line, "HT operation") != NULL) {
9247 ret = fgets(line, sizeof(line), f);
9248 sscanf(line," * secondary channel offset: %s", &buf);
9249 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009250 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009251 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 +08009252 }
developer615510b2022-09-27 10:14:35 +08009253 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009254 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009255 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9256 } else {
9257 //20Mhz
9258 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 +08009259 }
developer615510b2022-09-27 10:14:35 +08009260 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009261 continue;
developer615510b2022-09-27 10:14:35 +08009262 } else if (strstr(line, "HE capabilities") != NULL) {
9263 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9264 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9265 ret = fgets(line, sizeof(line), f);
9266 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9267 if (strstr(line, "HE40/2.4GHz") != NULL)
9268 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9269 else
9270 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9271 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9272 if (strstr(line, "HE80/5GHz") != NULL) {
9273 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9274 ret = fgets(line, sizeof(line), f);
9275 } else
9276 continue;
9277 if (strstr(line, "HE160/5GHz") != NULL)
9278 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009279 }
developer615510b2022-09-27 10:14:35 +08009280 continue;
9281 } else if (strstr(line, "WPA") != NULL) {
9282 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9283 } else if (strstr(line, "RSN") != NULL) {
9284 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9285 } else if (strstr(line, "Group cipher") != NULL) {
9286 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9287 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9288 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009289 }
developer06a01d92022-09-07 16:32:39 +08009290 }
developer615510b2022-09-27 10:14:35 +08009291 ret = fgets(line, sizeof(line), f);
9292 }
9293
9294 if (!filter_BSS) {
9295 *output_array_size = index + 1;
9296 } else {
9297 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9298 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009299 }
developer06a01d92022-09-07 16:32:39 +08009300 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009301 pclose(f);
developer5550e242022-09-30 09:59:32 +08009302 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009303 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009304 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009305}
developer615510b2022-09-27 10:14:35 +08009306
developer06a01d92022-09-07 16:32:39 +08009307INT wifi_getApAssociatedDeviceStats(
9308 INT apIndex,
9309 mac_address_t *clientMacAddress,
9310 wifi_associated_dev_stats_t *associated_dev_stats,
9311 u64 *handle)
9312{
9313 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9314 char interface_name[50] = {0};
9315 char cmd[1024] = {0};
9316 char mac_str[18] = {0};
9317 char *key = NULL;
9318 char *val = NULL;
9319 FILE *f = NULL;
9320 char *line = NULL;
9321 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009322
9323 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9324 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9325 return RETURN_ERR;
9326 }
9327
9328 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9329 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9330 if((f = popen(cmd, "r")) == NULL) {
9331 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9332 return RETURN_ERR;
9333 }
9334
developer30423732022-12-01 16:17:49 +08009335 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009336 key = strtok(line,":");
9337 val = strtok(NULL,":");
9338
9339 if(!strncmp(key,"rx bytes",8))
9340 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9341 if(!strncmp(key,"tx bytes",8))
9342 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9343 if(!strncmp(key,"rx packets",10))
9344 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9345 if(!strncmp(key,"tx packets",10))
9346 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9347 if(!strncmp(key,"tx retries",10))
9348 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9349 if(!strncmp(key,"tx failed",9))
9350 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9351 if(!strncmp(key,"rx drop misc",13))
9352 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9353 if(!strncmp(key,"rx bitrate",10)) {
9354 val = strtok(val, " ");
9355 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9356 }
9357 if(!strncmp(key,"tx bitrate",10)) {
9358 val = strtok(val, " ");
9359 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9360 }
9361 }
9362 free(line);
9363 pclose(f);
9364 return RETURN_OK;
9365}
9366
9367INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9368{
developerd946fd62022-12-08 18:03:28 +08009369 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009370 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9371
9372 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9373 if (NULL == output_string)
9374 return RETURN_ERR;
9375
developerac6f1142022-12-20 19:26:35 +08009376 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009377 return RETURN_ERR;
9378 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 +08009379 _syscmd(cmd, buf, sizeof(buf));
9380
9381 //size of SSID name restricted to value less than 32 bytes
9382 snprintf(output_string, 32, "%s", buf);
9383 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9384
9385 return RETURN_OK;
9386}
9387
9388INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9389{
9390 //char cmd[MAX_CMD_SIZE] = {0};
9391 char config_file[MAX_BUF_SIZE] = {0};
9392 char buf[32] = {0};
9393
9394 if (!output_filterMode)
9395 return RETURN_ERR;
9396
9397 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9398 //_syscmd(cmd, buf, sizeof(buf));
9399 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9400 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009401 if(strlen(buf) == 0) {
9402 *output_filterMode = 0;
9403 }
9404 else {
9405 int macaddr_acl_mode = strtol(buf, NULL, 10);
9406 if (macaddr_acl_mode == 1) {
9407 *output_filterMode = 1;
9408 } else if (macaddr_acl_mode == 0) {
9409 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9410 if (strlen(buf) == 0) {
9411 *output_filterMode = 0;
9412 } else {
9413 *output_filterMode = 2;
9414 }
9415 } else {
9416 return RETURN_ERR;
9417 }
9418 }
developer06a01d92022-09-07 16:32:39 +08009419
9420 return RETURN_OK;
9421}
9422
9423INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9424{
9425 FILE *fp = NULL;
9426 char str[MAX_BUF_SIZE] = {0};
9427 int wificlientindex = 0 ;
9428 int count = 0;
9429 int signalstrength = 0;
9430 int arr[MACADDRESS_SIZE] = {0};
9431 unsigned char mac[MACADDRESS_SIZE] = {0};
9432 UINT wifi_count = 0;
9433 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9434 char pipeCmd[MAX_CMD_SIZE] = {0};
9435
9436 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9437 *output_array_size = 0;
9438 *associated_dev_array = NULL;
9439 char interface_name[50] = {0};
9440
9441 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9442 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9443 return RETURN_ERR;
9444 }
9445
9446 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9447 fp = popen(pipeCmd, "r");
9448 if (fp == NULL)
9449 {
9450 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9451 return RETURN_ERR;
9452 }
9453
9454 /* Read the output a line at a time - output it. */
9455 fgets(str, sizeof(str)-1, fp);
9456 wifi_count = (unsigned int) atoi ( str );
9457 *output_array_size = wifi_count;
9458 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9459 pclose(fp);
9460
9461 if(wifi_count == 0)
9462 {
9463 return RETURN_OK;
9464 }
9465 else
9466 {
9467 wifi_associated_dev2_t* temp = NULL;
9468 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9469 *associated_dev_array = temp;
9470 if(temp == NULL)
9471 {
9472 printf("Error Statement. Insufficient memory \n");
9473 return RETURN_ERR;
9474 }
9475
9476 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9477 system(pipeCmd);
9478
9479 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9480 if(fp == NULL)
9481 {
9482 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9483 return RETURN_ERR;
9484 }
9485 fclose(fp);
9486
developer30423732022-12-01 16:17:49 +08009487 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009488 fp = popen(pipeCmd, "r");
9489 if(fp)
9490 {
9491 for(count =0 ; count < wifi_count; count++)
9492 {
9493 fgets(str, MAX_BUF_SIZE, fp);
9494 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9495 {
9496 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9497 {
9498 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9499
9500 }
9501 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9502 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]);
9503 }
9504 temp[count].cli_AuthenticationState = 1; //TODO
9505 temp[count].cli_Active = 1; //TODO
9506 }
9507 pclose(fp);
9508 }
9509
9510 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009511 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 +08009512 fp = popen(pipeCmd, "r");
9513 if(fp)
9514 {
9515 pclose(fp);
9516 }
9517 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9518 if(fp)
9519 {
9520 for(count =0 ; count < wifi_count ;count++)
9521 {
9522 fgets(str, MAX_BUF_SIZE, fp);
9523 signalstrength = atoi(str);
9524 temp[count].cli_RSSI = signalstrength;
9525 }
9526 pclose(fp);
9527 }
9528
9529
9530 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009531 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 +08009532 fp = popen(pipeCmd, "r");
9533 if (fp)
9534 {
9535 pclose(fp);
9536 }
9537 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9538 if (fp)
9539 {
9540 for (count = 0; count < wifi_count; count++)
9541 {
9542 fgets(str, MAX_BUF_SIZE, fp);
9543 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9544 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9545 }
9546 pclose(fp);
9547 }
9548
9549 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009550 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 +08009551 fp = popen(pipeCmd, "r");
9552 if (fp)
9553 {
9554 pclose(fp);
9555 }
9556 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9557 if (fp)
9558 {
9559 for (count = 0; count < wifi_count; count++)
9560 {
9561 fgets(str, MAX_BUF_SIZE, fp);
9562 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9563 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9564 }
9565 pclose(fp);
9566 }
9567 }
9568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9569 return RETURN_OK;
9570
9571}
9572
9573INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9574{
9575#if 0
9576 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009577 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009578 _syscmd(cmd, buf, sizeof(buf));*/
9579
9580 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9581 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9582 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9583 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9584
9585 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.
9586 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].
9587 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].
9588 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].
9589 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9590 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9591
9592 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9593 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9594 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9595 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.
9596 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.
9597 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.
9598 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.
9599 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.
9600 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.
9601 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.
9602 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9603#endif
9604
9605 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009606 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009607 char pipeCmd[128] = {0};
9608 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009609 wifi_ssidTrafficStats2_t *out = output_struct;
9610
developerce736392022-09-13 15:24:34 +08009611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009612 if (!output_struct)
9613 return RETURN_ERR;
9614
developerce736392022-09-13 15:24:34 +08009615 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009616 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009617 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009618 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009619
developer06a01d92022-09-07 16:32:39 +08009620 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009621 if (fp == NULL) {
9622 fprintf(stderr, "%s: popen failed\n", __func__);
9623 return RETURN_ERR;
9624 }
9625 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009626 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009627
developerce736392022-09-13 15:24:34 +08009628 if (strlen(str) == 0) // interface not exist
9629 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009630
developerce736392022-09-13 15:24:34 +08009631 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9632 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009633
developerce736392022-09-13 15:24:34 +08009634 memset(str, 0, sizeof(str));
9635 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009636 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009637 if (fp == NULL) {
9638 fprintf(stderr, "%s: popen failed\n", __func__);
9639 return RETURN_ERR;
9640 }
9641 fgets(str, sizeof(str), fp);
9642
9643 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9644 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009645 pclose(fp);
developerce736392022-09-13 15:24:34 +08009646
9647 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9648 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9649
9650 // Not supported
9651 output_struct->ssid_RetransCount = 0;
9652 output_struct->ssid_FailedRetransCount = 0;
9653 output_struct->ssid_RetryCount = 0;
9654 output_struct->ssid_MultipleRetryCount = 0;
9655 output_struct->ssid_ACKFailureCount = 0;
9656 output_struct->ssid_AggregatedPacketCount = 0;
9657
developer06a01d92022-09-07 16:32:39 +08009658 return RETURN_OK;
9659}
9660
9661//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).
9662INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9663{
9664 char output_val[16]={'\0'};
9665 char config_file[MAX_BUF_SIZE] = {0};
9666
9667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9668 if (!output)
9669 return RETURN_ERR;
9670 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9671 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9672
9673 if( strcmp(output_val,"1") == 0 )
9674 *output = TRUE;
9675 else
9676 *output = FALSE;
9677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9678
9679 return RETURN_OK;
9680}
9681
9682INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9683{
9684 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9685 char str[MAX_BUF_SIZE]={'\0'};
9686 char string[MAX_BUF_SIZE]={'\0'};
9687 char cmd[MAX_CMD_SIZE]={'\0'};
9688 char *ch;
9689 char config_file[MAX_BUF_SIZE] = {0};
9690 struct params params;
9691
9692 if(enable == TRUE)
9693 strcpy(string,"1");
9694 else
9695 strcpy(string,"0");
9696
9697 params.name = "ap_isolate";
9698 params.value = string;
9699
9700 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9701 wifi_hostapdWrite(config_file,&params,1);
9702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9703
9704 return RETURN_OK;
9705}
9706
9707INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9708{
9709 if (NULL == output_dBm)
9710 return RETURN_ERR;
9711
9712 *output_dBm = 0;
9713 return RETURN_OK;
9714}
9715
9716INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9717{
9718 return RETURN_OK;
9719}
9720INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9721{
9722 return RETURN_OK;
9723}
9724INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9725{
9726 return RETURN_OK;
9727}
9728INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9729{
9730 return RETURN_OK;
9731}
9732INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9733{
9734 return RETURN_OK;
9735}
9736INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9737{
9738 char config_file[MAX_BUF_SIZE] = {0};
9739 struct params list;
9740
9741 list.name = "bss_transition";
9742 list.value = activate?"1":"0";
9743 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9744 wifi_hostapdWrite(config_file, &list, 1);
9745
9746 return RETURN_OK;
9747}
9748wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9749
9750void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9751{
9752 return;
9753}
9754
9755INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9756{
9757 // TODO Implement me!
9758 return RETURN_OK;
9759}
9760
9761INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9762{
developera3c68b92022-09-13 15:27:29 +08009763 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009764 FILE *f = NULL;
9765
developer72ec5572023-01-05 16:27:13 +08009766 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009767
developer72ec5572023-01-05 16:27:13 +08009768 if (essid == NULL)
9769 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009770
developer72ec5572023-01-05 16:27:13 +08009771 if (strlen(essid) == 0 || apIndex == -1) {
9772 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9773 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009774 }
9775
developer72ec5572023-01-05 16:27:13 +08009776 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9777 f = fopen(file_name, "w");
9778 if (f == NULL)
9779 return RETURN_ERR;
9780
9781 // For mode == 0 is to disable filter, just don't write ssid to the file.
9782 fprintf(f, "%d\n%s", mode, mode?essid:"");
9783 fclose(f);
9784 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009785 return RETURN_OK;
9786}
9787
9788INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9789{
9790 // TODO Implement me!
9791 //Apply wifi_pushRadioChannel() instantly
9792 return RETURN_ERR;
9793}
9794
9795INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9796{
9797 // TODO Implement me!
9798 return RETURN_OK;
9799}
9800
9801#ifdef HAL_NETLINK_IMPL
9802static int tidStats_callback(struct nl_msg *msg, void *arg) {
9803 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9804 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9805 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9806 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9807 int rem , tid_index = 0;
9808
9809 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9810 wifi_associated_dev_tid_entry_t *stats_entry;
9811
9812 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9813 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9814 };
9815 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9816 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9817 };
9818
9819 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9820 genlmsg_attrlen(gnlh, 0), NULL);
9821
9822
9823 if (!tb[NL80211_ATTR_STA_INFO]) {
9824 fprintf(stderr, "station stats missing!\n");
9825 return NL_SKIP;
9826 }
9827
9828 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9829 tb[NL80211_ATTR_STA_INFO],
9830 stats_policy)) {
9831 fprintf(stderr, "failed to parse nested attributes!\n");
9832 return NL_SKIP;
9833 }
9834
9835 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9836 {
9837 stats_entry = &out->tid_array[tid_index];
9838
9839 stats_entry->tid = tid_index;
9840 stats_entry->ac = _tid_ac_index_get[tid_index];
9841
9842 if(sinfo[NL80211_STA_INFO_TID_STATS])
9843 {
9844 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9845 printf("failed to parse nested stats attributes!");
9846 return NL_SKIP;
9847 }
9848 }
9849 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9850 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9851
9852 if(tid_index < (PS_MAX_TID - 1))
9853 tid_index++;
9854 }
9855 //ToDo: sum_time_ms, ewma_time_ms
9856 return NL_SKIP;
9857}
9858#endif
9859
9860INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9861{
9862#ifdef HAL_NETLINK_IMPL
9863 Netlink nl;
9864 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009865 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009866
developerac6f1142022-12-20 19:26:35 +08009867 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009868 return RETURN_ERR;
9869
9870 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009871
9872 nl.id = initSock80211(&nl);
9873
9874 if (nl.id < 0) {
9875 fprintf(stderr, "Error initializing netlink \n");
9876 return -1;
9877 }
9878
9879 struct nl_msg* msg = nlmsg_alloc();
9880
9881 if (!msg) {
9882 fprintf(stderr, "Failed to allocate netlink message.\n");
9883 nlfree(&nl);
9884 return -2;
9885 }
9886
9887 genlmsg_put(msg,
9888 NL_AUTO_PORT,
9889 NL_AUTO_SEQ,
9890 nl.id,
9891 0,
9892 0,
9893 NL80211_CMD_GET_STATION,
9894 0);
9895
9896 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9897 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9898 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9899 nl_send_auto(nl.socket, msg);
9900 nl_recvmsgs(nl.socket, nl.cb);
9901 nlmsg_free(msg);
9902 nlfree(&nl);
9903 return RETURN_OK;
9904#else
9905//iw implementation
9906#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9907#define TOTAL_MAX_LINES 50
9908
9909 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009910 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009911 FILE *fp=NULL;
9912 char pipeCmd[1024]= {'\0'};
9913 int lines,tid_index=0;
9914 char mac_addr[20] = {'\0'};
9915
developerac6f1142022-12-20 19:26:35 +08009916 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009917 return RETURN_ERR;
9918
developer06a01d92022-09-07 16:32:39 +08009919 wifi_associated_dev_tid_entry_t *stats_entry;
9920
developer06a01d92022-09-07 16:32:39 +08009921 strcpy(mac_addr,clientMacAddress);
9922
9923 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9924 fp= popen(pipeCmd,"r");
9925 if(fp == NULL)
9926 {
9927 perror("popen for station dump failed\n");
9928 return RETURN_ERR;
9929 }
9930 pclose(fp);
9931
9932 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9933 fp=popen(pipeCmd,"r");
9934 if(fp == NULL)
9935 {
9936 perror("popen for grep station failed\n");
9937 return RETURN_ERR;
9938 }
9939 else if(fgets(buf,sizeof(buf),fp) != NULL)
9940 lines=atoi(buf);
9941 else
9942 {
9943 pclose(fp);
9944 fprintf(stderr,"No devices are connected \n");
9945 return RETURN_ERR;
9946 }
9947 pclose(fp);
9948
9949 if(lines == 1)
9950 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9951
9952 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9953 {
9954 stats_entry = &tid_stats->tid_array[tid_index];
9955 stats_entry->tid = tid_index;
9956
9957 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);
9958
9959 fp=popen(pipeCmd,"r");
9960 if(fp ==NULL)
9961 {
9962 perror("Failed to read from tid file \n");
9963 return RETURN_ERR;
9964 }
9965 else if(fgets(buf,sizeof(buf),fp) != NULL)
9966 stats_entry->num_msdus = atol(buf);
9967
9968 pclose(fp);
9969 stats_entry->ac = _tid_ac_index_get[tid_index];
9970// TODO:
9971// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9972// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9973 }
9974 return RETURN_OK;
9975#endif
9976}
9977
9978
9979INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9980{
developerd946fd62022-12-08 18:03:28 +08009981 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009982 char cmd[128]={0};
9983 char buf[128]={0};
9984 int freq = 0;
9985
9986 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9987
9988 // full mode is used to scan all channels.
9989 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9990 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9991 ieee80211_channel_to_frequency(chan_list[0], &freq);
9992
developerac6f1142022-12-20 19:26:35 +08009993 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009994 return RETURN_ERR;
9995
developer615510b2022-09-27 10:14:35 +08009996 if (freq)
developerd946fd62022-12-08 18:03:28 +08009997 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009998 else
developerd946fd62022-12-08 18:03:28 +08009999 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +080010000
10001 _syscmd(cmd, buf, sizeof(buf));
10002 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10003
developer06a01d92022-09-07 16:32:39 +080010004 return RETURN_OK;
10005}
10006
10007
10008INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10009{
10010 // TODO Implement me!
10011 return RETURN_ERR;
10012}
10013
10014INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10015{
10016 // TODO Implement me!
10017 return RETURN_ERR;
10018}
10019
10020INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10021{
10022 // TODO Implement me!
10023 return RETURN_ERR;
10024}
10025
10026INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10027{
10028 // TODO Implement me!
10029 return RETURN_ERR;
10030}
10031
10032INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10033{
10034 // TODO Implement me!
10035 return RETURN_ERR;
10036}
10037
10038INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10039{
10040 // TODO Implement me!
10041 return RETURN_ERR;
10042}
10043
10044INT wifi_steering_eventUnregister(void)
10045{
10046 // TODO Implement me!
10047 return RETURN_ERR;
10048}
10049
10050INT wifi_delApAclDevices(INT apIndex)
10051{
10052#if 0
10053 char cmd[MAX_BUF_SIZE] = {0};
10054 char buf[MAX_BUF_SIZE] = {0};
10055
10056 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010057 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010058 if(_syscmd(cmd,buf,sizeof(buf)))
10059 return RETURN_ERR;
10060#endif
developer9988c232023-03-06 14:57:08 +080010061 char cmd[256]={0};
10062 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010063
developere6aafda2022-09-13 14:59:28 +080010064 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010065 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 +080010066 if(_syscmd(cmd, buf, sizeof(buf)))
10067 return RETURN_ERR;
10068 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010069
10070 return RETURN_OK;
10071}
10072
10073#ifdef HAL_NETLINK_IMPL
10074static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10075 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10076 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10077 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10078 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10079 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10080 char mac_addr[20],dev[20];
10081
10082 nla_parse(tb,
10083 NL80211_ATTR_MAX,
10084 genlmsg_attrdata(gnlh, 0),
10085 genlmsg_attrlen(gnlh, 0),
10086 NULL);
10087
10088 if(!tb[NL80211_ATTR_STA_INFO]) {
10089 fprintf(stderr, "sta stats missing!\n");
10090 return NL_SKIP;
10091 }
10092
10093 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10094 fprintf(stderr, "failed to parse nested attributes!\n");
10095 return NL_SKIP;
10096 }
10097 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10098
10099 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10100
10101 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10102 fprintf(stderr, "failed to parse nested rate attributes!");
10103 return NL_SKIP;
10104 }
10105
10106 if(sinfo[NL80211_STA_INFO_TID_STATS])
10107 {
10108 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10109 printf("failed to parse nested stats attributes!");
10110 return NL_SKIP;
10111 }
10112 }
10113
10114 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10115 {
10116 printf("Type is VHT\n");
10117 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10118 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10119
10120 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10121 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10122 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10123 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10124 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10125 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10126 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10127 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10128 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10129 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10130 }
10131 else
10132 {
10133 printf(" OFDM or CCK \n");
10134 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10135 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10136 }
10137
10138 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10139 if(rinfo[NL80211_RATE_INFO_MCS])
10140 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10141 }
10142 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10143 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10144 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10145 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10146
10147 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10148 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10149
10150 if (sinfo[NL80211_STA_INFO_SIGNAL])
10151 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10152 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10153 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10154 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10155 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10156 //rssi_array need to be filled
10157 return NL_SKIP;
10158}
10159#endif
10160
10161INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10162{
10163#ifdef HAL_NETLINK_IMPL
10164 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010165 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010166 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010167 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010168
10169 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10170
10171 if (*output_array_size <= 0)
10172 return RETURN_OK;
10173
developer06a01d92022-09-07 16:32:39 +080010174 nl.id = initSock80211(&nl);
10175
10176 if (nl.id < 0) {
10177 fprintf(stderr, "Error initializing netlink \n");
10178 return 0;
10179 }
10180
10181 struct nl_msg* msg = nlmsg_alloc();
10182
10183 if (!msg) {
10184 fprintf(stderr, "Failed to allocate netlink message.\n");
10185 nlfree(&nl);
10186 return 0;
10187 }
10188
10189 genlmsg_put(msg,
10190 NL_AUTO_PORT,
10191 NL_AUTO_SEQ,
10192 nl.id,
10193 0,
10194 0,
10195 NL80211_CMD_GET_STATION,
10196 0);
10197
10198 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10199 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10200 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10201 nl_send_auto(nl.socket, msg);
10202 nl_recvmsgs(nl.socket, nl.cb);
10203 nlmsg_free(msg);
10204 nlfree(&nl);
10205 return RETURN_OK;
10206#else
10207 //TODO Implement me
10208 return RETURN_OK;
10209#endif
10210}
10211
10212#ifdef HAL_NETLINK_IMPL
10213static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10214 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10215 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10216 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10217 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10218 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10219 char mac_addr[20],dev[20];
10220
10221 nla_parse(tb,
10222 NL80211_ATTR_MAX,
10223 genlmsg_attrdata(gnlh, 0),
10224 genlmsg_attrlen(gnlh, 0),
10225 NULL);
10226
10227 if(!tb[NL80211_ATTR_STA_INFO]) {
10228 fprintf(stderr, "sta stats missing!\n");
10229 return NL_SKIP;
10230 }
10231
10232 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10233 fprintf(stderr, "failed to parse nested attributes!\n");
10234 return NL_SKIP;
10235 }
10236
10237 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10238
10239 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10240
10241 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10242 fprintf(stderr, "failed to parse nested rate attributes!");
10243 return NL_SKIP;
10244 }
10245
10246 if(sinfo[NL80211_STA_INFO_TID_STATS])
10247 {
10248 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10249 printf("failed to parse nested stats attributes!");
10250 return NL_SKIP;
10251 }
10252 }
10253 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10254 {
10255 printf("Type is VHT\n");
10256 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10257 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10258
10259 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10260 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10261 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10262 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10263 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10264 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10265 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10266 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10267 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10268 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10269 }
10270 else
10271 {
10272 printf(" OFDM or CCK \n");
10273 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10274 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10275 }
10276
10277 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10278 if(rinfo[NL80211_RATE_INFO_MCS])
10279 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10280 }
10281
10282 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10283 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10284 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10285 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10286
10287 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10288 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10289 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10290
10291 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10292 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10293
10294 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10295 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10296
10297 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10298 ((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]);
10299
10300 return NL_SKIP;
10301}
10302#endif
10303
10304INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10305{
10306#ifdef HAL_NETLINK_IMPL
10307 Netlink nl;
10308 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010309 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010310 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010311 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010312
10313 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10314
10315 if (*output_array_size <= 0)
10316 return RETURN_OK;
10317
developerd946fd62022-12-08 18:03:28 +080010318 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010319
10320 nl.id = initSock80211(&nl);
10321
10322 if(nl.id < 0) {
10323 fprintf(stderr, "Error initializing netlink \n");
10324 return 0;
10325 }
10326
10327 struct nl_msg* msg = nlmsg_alloc();
10328
10329 if(!msg) {
10330 fprintf(stderr, "Failed to allocate netlink message.\n");
10331 nlfree(&nl);
10332 return 0;
10333 }
10334
10335 genlmsg_put(msg,
10336 NL_AUTO_PORT,
10337 NL_AUTO_SEQ,
10338 nl.id,
10339 0,
10340 0,
10341 NL80211_CMD_GET_STATION,
10342 0);
10343
10344 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10345 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10346 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10347 nl_send_auto(nl.socket, msg);
10348 nl_recvmsgs(nl.socket, nl.cb);
10349 nlmsg_free(msg);
10350 nlfree(&nl);
10351 return RETURN_OK;
10352#else
10353 //TODO Implement me
10354 return RETURN_OK;
10355#endif
10356}
10357
10358INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10359{
10360 // TODO Implement me!
10361 char buf[MAX_BUF_SIZE] = {0};
10362 char config_file[MAX_BUF_SIZE] = {0};
10363
10364 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10365 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10366 *activate = (strncmp("1",buf,1) == 0);
10367
10368 return RETURN_OK;
10369}
10370
10371INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10372{
10373 char config_file[MAX_BUF_SIZE] = {0};
10374 struct params list;
10375
10376 list.name = "rrm_neighbor_report";
10377 list.value = activate?"1":"0";
10378 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10379 wifi_hostapdWrite(config_file, &list, 1);
10380
10381 return RETURN_OK;
10382}
10383
10384INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10385{
10386 char buf[32] = {0};
10387 char config_file[MAX_BUF_SIZE] = {0};
10388
10389 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10390 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10391 *activate = (strncmp("1",buf,1) == 0);
10392
10393 return RETURN_OK;
10394}
10395#undef HAL_NETLINK_IMPL
10396#ifdef HAL_NETLINK_IMPL
10397static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10398 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10399 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10400 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10401 char dev[20];
10402 int freq =0 ;
10403 static int i=0;
10404
10405 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10406
10407 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10408 };
10409
10410 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10411
10412 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10413
10414 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10415 fprintf(stderr, "survey data missing!\n");
10416 return NL_SKIP;
10417 }
10418
10419 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10420 {
10421 fprintf(stderr, "failed to parse nested attributes!\n");
10422 return NL_SKIP;
10423 }
10424
10425
10426 if(out[0].array_size == 1 )
10427 {
10428 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10429 {
10430 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10431 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10432 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10433
10434 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10435 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10436 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10437 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10438 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10439 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10440 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10441 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10442 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10443 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10444 if (sinfo[NL80211_SURVEY_INFO_TIME])
10445 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10446 return NL_STOP;
10447 }
10448 }
10449 else
10450 {
10451 if ( i <= out[0].array_size )
10452 {
10453 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10454 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10455 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10456
10457 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10458 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10459 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10460 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10461 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10462 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10463 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10464 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10465 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10466 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10467 if (sinfo[NL80211_SURVEY_INFO_TIME])
10468 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10469 }
10470 }
10471
10472 i++;
10473 return NL_SKIP;
10474}
10475#endif
10476
10477static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10478{
10479 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10480 FILE *fp;
10481
10482 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10483 {
10484 printf("Creating Frequency-Channel Map\n");
10485 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10486 }
10487 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10488 if((fp = popen(command, "r")))
10489 {
10490 fgets(output, sizeof(output), fp);
10491 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010492 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010493 }
10494
10495 return 0;
10496}
10497
10498static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10499{
10500 int freqMHz = -1;
10501 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010502 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010503
10504 ieee80211_channel_to_frequency(channel, &freqMHz);
10505 if (freqMHz == -1) {
10506 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10507 return -1;
10508 }
10509
developer7930d352022-12-21 17:55:42 +080010510 wifi_GetInterfaceName(radioIndex, interface_name);
10511 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010512 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10513 radioIndex, freqMHz);
10514 return -1;
10515 }
10516
10517 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10518 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10519 return -1;
10520 }
10521
10522 return 0;
10523}
10524
10525static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10526{
10527 const char *ptr = buf;
10528 char *key = NULL;
10529 char *val = NULL;
10530 char line[256] = { '\0' };
10531
10532 while (ptr = get_line_from_str_buf(ptr, line)) {
10533 if (strstr(line, "Frequency")) continue;
10534
10535 key = strtok(line, ":");
10536 val = strtok(NULL, " ");
10537 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10538
10539 if (!strcmp(key, "noise")) {
10540 sscanf(val, "%d", &stats->ch_noise);
10541 if (stats->ch_noise == 0) {
10542 // Workaround for missing noise information.
10543 // Assume -95 for 2.4G and -103 for 5G
10544 if (radioIndex == 0) stats->ch_noise = -95;
10545 if (radioIndex == 1) stats->ch_noise = -103;
10546 }
10547 }
10548 else if (!strcmp(key, "channel active time")) {
10549 sscanf(val, "%llu", &stats->ch_utilization_total);
10550 }
10551 else if (!strcmp(key, "channel busy time")) {
10552 sscanf(val, "%llu", &stats->ch_utilization_busy);
10553 }
10554 else if (!strcmp(key, "channel receive time")) {
10555 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10556 }
10557 else if (!strcmp(key, "channel transmit time")) {
10558 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10559 }
10560 };
10561
10562 return 0;
10563}
10564
10565INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10566{
10567 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10568#ifdef HAL_NETLINK_IMPL
10569 Netlink nl;
10570 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010571 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010572
10573 local[0].array_size = array_size;
10574
developerac6f1142022-12-20 19:26:35 +080010575 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010576 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010577
10578 nl.id = initSock80211(&nl);
10579
10580 if (nl.id < 0) {
10581 fprintf(stderr, "Error initializing netlink \n");
10582 return -1;
10583 }
10584
10585 struct nl_msg* msg = nlmsg_alloc();
10586
10587 if (!msg) {
10588 fprintf(stderr, "Failed to allocate netlink message.\n");
10589 nlfree(&nl);
10590 return -2;
10591 }
10592
10593 genlmsg_put(msg,
10594 NL_AUTO_PORT,
10595 NL_AUTO_SEQ,
10596 nl.id,
10597 0,
10598 NLM_F_DUMP,
10599 NL80211_CMD_GET_SURVEY,
10600 0);
10601
10602 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10603 nl_send_auto(nl.socket, msg);
10604 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10605 nl_recvmsgs(nl.socket, nl.cb);
10606 nlmsg_free(msg);
10607 nlfree(&nl);
10608 //Copying the Values
10609 for(int i=0;i<array_size;i++)
10610 {
10611 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10612 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10613 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10614 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10615 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10616 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10617 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10618 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10619 }
10620#else
10621 ULONG channel = 0;
10622 int i;
10623 int number_of_channels = array_size;
10624 char buf[512];
10625 INT ret;
10626 wifi_channelStats_t tmp_stats;
10627
10628 if (number_of_channels == 0) {
10629 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10630 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10631 return RETURN_ERR;
10632 }
10633 number_of_channels = 1;
10634 input_output_channelStats_array[0].ch_number = channel;
10635 }
10636
10637 for (i = 0; i < number_of_channels; i++) {
10638
10639 input_output_channelStats_array[i].ch_noise = 0;
10640 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10641 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10642 input_output_channelStats_array[i].ch_utilization_busy = 0;
10643 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10644 input_output_channelStats_array[i].ch_utilization_total = 0;
10645
10646 memset(buf, 0, sizeof(buf));
10647 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10648 return RETURN_ERR;
10649 }
10650 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10651 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10652 return RETURN_ERR;
10653 }
10654
10655 // XXX: fake missing 'self' counter which is not available in iw survey output
10656 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10657 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10658
10659 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10660 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10661 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10662 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10663 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10664
10665 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",
10666 __func__,
10667 input_output_channelStats_array[i].ch_number,
10668 input_output_channelStats_array[i].ch_noise,
10669 input_output_channelStats_array[i].ch_utilization_total,
10670 input_output_channelStats_array[i].ch_utilization_busy,
10671 input_output_channelStats_array[i].ch_utilization_busy_rx,
10672 input_output_channelStats_array[i].ch_utilization_busy_tx,
10673 input_output_channelStats_array[i].ch_utilization_busy_self,
10674 input_output_channelStats_array[i].ch_utilization_busy_ext);
10675 }
10676#endif
10677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10678 return RETURN_OK;
10679}
10680#define HAL_NETLINK_IMPL
10681
10682/* Hostapd events */
10683
10684#ifndef container_of
10685#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10686#define container_of(ptr, type, member) \
10687 ((type *)((char *)ptr - offset_of(type, member)))
10688#endif /* container_of */
10689
10690struct ctrl {
10691 char sockpath[128];
10692 char sockdir[128];
10693 char bss[IFNAMSIZ];
10694 char reply[4096];
10695 int ssid_index;
10696 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10697 void (*overrun)(struct ctrl *ctrl);
10698 struct wpa_ctrl *wpa;
10699 unsigned int ovfl;
10700 size_t reply_len;
10701 int initialized;
10702 ev_timer retry;
10703 ev_timer watchdog;
10704 ev_stat stat;
10705 ev_io io;
10706};
10707static wifi_newApAssociatedDevice_callback clients_connect_cb;
10708static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10709static struct ctrl wpa_ctrl[MAX_APS];
10710static int initialized;
10711
10712static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10713{
10714 char cbuf[256] = {};
10715 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10716 struct cmsghdr *cmsg;
10717 unsigned int ovfl = ctrl->ovfl;
10718 unsigned int drop;
10719
10720 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10721 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10722 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10723 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10724
10725 drop = ovfl - ctrl->ovfl;
10726 ctrl->ovfl = ovfl;
10727
10728 return drop;
10729}
10730
10731static void ctrl_close(struct ctrl *ctrl)
10732{
10733 if (ctrl->io.cb)
10734 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10735 if (ctrl->retry.cb)
10736 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10737 if (!ctrl->wpa)
10738 return;
10739
10740 wpa_ctrl_detach(ctrl->wpa);
10741 wpa_ctrl_close(ctrl->wpa);
10742 ctrl->wpa = NULL;
10743 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10744}
10745
10746static void ctrl_process(struct ctrl *ctrl)
10747{
10748 const char *str;
10749 int drops;
10750 int level;
10751 int err;
10752
10753 /* Example events:
10754 *
10755 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10756 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10757 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10758 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10759 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10760 */
10761 if (!(str = index(ctrl->reply, '>')))
10762 return;
10763 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10764 return;
10765
10766 str++;
10767
10768 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10769 if (!(str = index(ctrl->reply, ' ')))
10770 return;
10771 wifi_associated_dev_t sta;
10772 memset(&sta, 0, sizeof(sta));
10773
10774 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10775 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10776 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10777
10778 sta.cli_Active=true;
10779
10780 (clients_connect_cb)(ctrl->ssid_index, &sta);
10781 goto handled;
10782 }
10783
10784 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10785 if (!(str = index(ctrl->reply, ' ')))
10786 return;
10787
10788 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10789 goto handled;
10790 }
10791
10792 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10793 printf("CTRL_WPA: handle TERMINATING event\n");
10794 goto retry;
10795 }
10796
10797 if (strncmp("AP-DISABLED", str, 11) == 0) {
10798 printf("CTRL_WPA: handle AP-DISABLED\n");
10799 goto retry;
10800 }
10801
10802 printf("Event not supported!!\n");
10803
10804handled:
10805
10806 if ((drops = ctrl_get_drops(ctrl))) {
10807 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10808 if (ctrl->overrun)
10809 ctrl->overrun(ctrl);
10810 }
10811
10812 return;
10813
10814retry:
10815 printf("WPA_CTRL: closing\n");
10816 ctrl_close(ctrl);
10817 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10818 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10819}
10820
10821static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10822{
10823 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10824 int err;
10825
10826 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10827 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10828 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10829 ctrl->reply[ctrl->reply_len] = 0;
10830 if (err < 0) {
10831 if (errno == EAGAIN || errno == EWOULDBLOCK)
10832 return;
10833 ctrl_close(ctrl);
10834 ev_timer_again(EV_A_ &ctrl->retry);
10835 return;
10836 }
10837
10838 ctrl_process(ctrl);
10839}
10840
10841static int ctrl_open(struct ctrl *ctrl)
10842{
10843 int fd;
10844
10845 if (ctrl->wpa)
10846 return 0;
10847
10848 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10849 if (!ctrl->wpa)
10850 goto err;
10851
10852 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10853 goto err_close;
10854
10855 fd = wpa_ctrl_get_fd(ctrl->wpa);
10856 if (fd < 0)
10857 goto err_detach;
10858
10859 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10860 goto err_detach;
10861
10862 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10863 ev_io_start(EV_DEFAULT_ &ctrl->io);
10864
10865 return 0;
10866
10867err_detach:
10868 wpa_ctrl_detach(ctrl->wpa);
10869err_close:
10870 wpa_ctrl_close(ctrl->wpa);
10871err:
10872 ctrl->wpa = NULL;
10873 return -1;
10874}
10875
10876static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10877{
10878 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10879
10880 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10881 ctrl_open(ctrl);
10882}
10883
10884static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10885{
10886 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10887
10888 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10889 if (ctrl_open(ctrl) == 0) {
10890 printf("WPA_CTRL: retry successful\n");
10891 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10892 }
10893}
10894
10895int ctrl_enable(struct ctrl *ctrl)
10896{
10897 if (ctrl->wpa)
10898 return 0;
10899
10900 if (!ctrl->stat.cb) {
10901 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10902 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10903 }
10904
10905 if (!ctrl->retry.cb) {
10906 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10907 }
10908
10909 return ctrl_open(ctrl);
10910}
10911
10912static void
10913ctrl_msg_cb(char *buf, size_t len)
10914{
10915 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10916
10917 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10918 ctrl_process(ctrl);
10919}
10920
10921static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10922{
10923 int err;
10924
10925 if (!ctrl->wpa)
10926 return -1;
10927 if (*reply_len < 2)
10928 return -1;
10929
10930 (*reply_len)--;
10931 ctrl->reply_len = sizeof(ctrl->reply);
10932 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10933 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10934 if (err < 0)
10935 return err;
10936
10937 if (ctrl->reply_len > *reply_len)
10938 ctrl->reply_len = *reply_len;
10939
10940 *reply_len = ctrl->reply_len;
10941 memcpy(reply, ctrl->reply, *reply_len);
10942 reply[*reply_len - 1] = 0;
10943 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10944 return 0;
10945}
10946
10947static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10948{
10949 const char *pong = "PONG";
10950 const char *ping = "PING";
10951 char reply[1024];
10952 size_t len = sizeof(reply);
10953 int err;
10954 ULONG s, snum;
10955 INT ret;
10956 BOOL status;
10957
10958 printf("WPA_CTRL: watchdog cb\n");
10959
10960 ret = wifi_getSSIDNumberOfEntries(&snum);
10961 if (ret != RETURN_OK) {
10962 printf("%s: failed to get SSID count", __func__);
10963 return;
10964 }
10965
10966 if (snum > MAX_APS) {
10967 printf("more ssid than supported! %lu\n", snum);
10968 return;
10969 }
10970
10971 for (s = 0; s < snum; s++) {
10972 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010973 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010974 continue;
10975 }
10976 if (status == false) continue;
10977
10978 memset(reply, 0, sizeof(reply));
10979 len = sizeof(reply);
10980 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10981 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10982 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10983 continue;
10984
10985 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10986 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010987 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010988 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10989 }
10990}
10991
10992static int init_wpa()
10993{
10994 int ret = 0, i = 0;
10995 ULONG s, snum;
10996
10997 ret = wifi_getSSIDNumberOfEntries(&snum);
10998 if (ret != RETURN_OK) {
10999 printf("%s: failed to get SSID count", __func__);
11000 return RETURN_ERR;
11001 }
11002
11003 if (snum > MAX_APS) {
11004 printf("more ssid than supported! %lu\n", snum);
11005 return RETURN_ERR;
11006 }
11007
11008 for (s = 0; s < snum; s++) {
11009 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11010 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11011 wpa_ctrl[s].ssid_index = s;
11012 ctrl_enable(&wpa_ctrl[s]);
11013 }
11014
11015 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11016 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11017
11018 initialized = 1;
11019 printf("WPA_CTRL: initialized\n");
11020
11021 return RETURN_OK;
11022}
11023
11024void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11025{
11026 clients_connect_cb = callback_proc;
11027 if (!initialized)
11028 init_wpa();
11029}
11030
11031void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11032{
11033 clients_disconnect_cb = callback_proc;
11034 if (!initialized)
11035 init_wpa();
11036}
11037
11038INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11039{
11040 // TODO Implement me!
11041 return RETURN_ERR;
11042}
11043
11044INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11045{
11046 // TODO Implement me!
11047 return RETURN_ERR;
11048}
11049
11050INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11051{
11052 int i;
developer4b102122023-02-15 10:53:03 +080011053 int phyId = -1;
11054 char cmd[256] = {0};
11055 char channel_numbers_buf[256] = {0};
11056 char dfs_state_buf[256] = {0};
11057 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011058 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011059 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080011060
developer4b102122023-02-15 10:53:03 +080011061 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011062
developer4b102122023-02-15 10:53:03 +080011063 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11064 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011065
developer4b102122023-02-15 10:53:03 +080011066 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 +080011067
developer4b102122023-02-15 10:53:03 +080011068 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11069 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11070 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011071 }
11072
developer4b102122023-02-15 10:53:03 +080011073 ptr = channel_numbers_buf;
11074 i = 0;
11075 while (ptr = get_line_from_str_buf(ptr, line)) {
11076 if (i >= outputMapSize) {
11077 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11078 return RETURN_ERR;
11079 }
11080 sscanf(line, "%d", &outputMap[i].ch_number);
11081
11082 memset(cmd, 0, sizeof(cmd));
11083 // Below command should fetch string for DFS state (usable, available or unavailable)
11084 // Example line: "DFS state: usable (for 78930 sec)"
11085 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) {
11086 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011087 return RETURN_ERR;
11088 }
11089
developer4b102122023-02-15 10:53:03 +080011090 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11091 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011092 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11093 return RETURN_ERR;
11094 }
11095
developer4b102122023-02-15 10:53:03 +080011096 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011097
developer4b102122023-02-15 10:53:03 +080011098 if (!strcmp(dfs_state_buf, "usable")) {
11099 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11100 } else if (!strcmp(dfs_state_buf, "available")) {
11101 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11102 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11103 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11104 } else {
11105 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011106 }
developer4b102122023-02-15 10:53:03 +080011107 i++;
developer06a01d92022-09-07 16:32:39 +080011108 }
11109
developer4b102122023-02-15 10:53:03 +080011110 return RETURN_OK;
11111
developer06a01d92022-09-07 16:32:39 +080011112 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11113 return RETURN_ERR;
11114}
11115
11116INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11117{
11118 // TODO Implement me!
11119 return RETURN_ERR;
11120}
11121
11122INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11123{
11124 return RETURN_OK;
11125}
11126
11127INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11128{
11129 // TODO Implement me!
11130 return RETURN_ERR;
11131}
11132
11133INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11134{
11135 // TODO API refrence Implementaion is present on RPI hal
11136 return RETURN_ERR;
11137}
11138
developerfeab1d12023-09-27 11:29:38 +080011139
developer06a01d92022-09-07 16:32:39 +080011140INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11141{
developera5005b62022-09-13 15:43:35 +080011142 char cmd[128]={'\0'};
11143 char buf[128]={'\0'};
developerfeab1d12023-09-27 11:29:38 +080011144 int radioIndex = -1;
11145 int phyIndex = -1;
11146 bool enabled = false;
11147 int cur_tx_dbm = 0;
developera5005b62022-09-13 15:43:35 +080011148
11149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfeab1d12023-09-27 11:29:38 +080011150
developera5005b62022-09-13 15:43:35 +080011151 if(txpwr_pcntg == NULL)
11152 return RETURN_ERR;
11153
developerfeab1d12023-09-27 11:29:38 +080011154 // The API name as getRadioXXX, I think the input index should be radioIndex,
11155 // but current we not change the name, but use it as radioIndex
11156 radioIndex = apIndex;
11157 phyIndex = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +080011158
developera5005b62022-09-13 15:43:35 +080011159 // Get the maximum tx power of the device
developerfeab1d12023-09-27 11:29:38 +080011160 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11161 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011162 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011163 if (strcmp(buf, "enable") == 0)
11164 enabled = true;
developera5005b62022-09-13 15:43:35 +080011165
developerfeab1d12023-09-27 11:29:38 +080011166 if (!enabled) {
11167 *txpwr_pcntg = 100;
11168 return RETURN_OK;
11169 }
11170
developera5005b62022-09-13 15:43:35 +080011171 memset(cmd, 0, sizeof(cmd));
11172 memset(buf, 0, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011173 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11174 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011175 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011176 cur_tx_dbm = strtol(buf, NULL, 10);
developera5005b62022-09-13 15:43:35 +080011177
developerfeab1d12023-09-27 11:29:38 +080011178 switch (cur_tx_dbm) {
11179 case 0:
11180 *txpwr_pcntg = 100; // range 91-100
developera5005b62022-09-13 15:43:35 +080011181 break;
developerfeab1d12023-09-27 11:29:38 +080011182 case 1:
11183 *txpwr_pcntg = 75; // range 61-90
11184 break;
11185 case 3:
11186 *txpwr_pcntg = 50; // range 31-60
11187 break;
11188 case 6:
11189 *txpwr_pcntg = 25; // range 16-30
11190 break;
11191 case 9:
11192 *txpwr_pcntg = 12; // range 10-15
11193 break;
11194 case 12:
11195 *txpwr_pcntg = 6; // range 1-9
11196 break;
11197 default:
11198 *txpwr_pcntg = 100; // 0
developera5005b62022-09-13 15:43:35 +080011199 }
developerfeab1d12023-09-27 11:29:38 +080011200
developer06a01d92022-09-07 16:32:39 +080011201 return RETURN_OK;
11202}
11203
11204INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11205{
developer58599c22022-09-13 16:40:34 +080011206 // TODO precac feature.
11207 struct params params = {0};
11208 char config_file[128] = {0};
11209
11210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11211
11212 params.name = "enable_background_radar";
11213 params.value = enable?"1":"0";
11214 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11215 wifi_hostapdWrite(config_file, &params, 1);
11216 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11217
11218 /* TODO precac feature */
11219
11220 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11221 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011222}
11223
11224INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11225{
developer58599c22022-09-13 16:40:34 +080011226 char config_file[128] = {0};
11227 char buf[64] = {0};
11228
11229 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11230 if (NULL == enable || NULL == precac)
11231 return RETURN_ERR;
11232
11233 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11234 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011235 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011236 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011237 *precac = true;
11238 } else {
developer58599c22022-09-13 16:40:34 +080011239 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011240 *precac = false;
11241 }
developer58599c22022-09-13 16:40:34 +080011242
11243 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11244 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011245}
11246
11247INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11248{
developer58599c22022-09-13 16:40:34 +080011249 *supported = TRUE;
11250 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011251}
11252
developera7149722023-01-11 11:36:21 +080011253bool check_is_hemu_vendor_new_patch() {
11254 char cmd[128] = {0};
11255 char buf[128] = {0};
11256
11257 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11258 _syscmd(cmd, buf, sizeof(buf));
11259
11260 if (strlen(buf) > 0)
11261 return FALSE;
11262 else
11263 return TRUE;
11264}
11265
developer3e6b1692022-09-30 18:04:05 +080011266INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11267{
11268 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11269 struct params params = {0};
11270 char config_file[64] = {0};
11271 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011272 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011273 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011274 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011275 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11276
developera7149722023-01-11 11:36:21 +080011277 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011278
11279 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11280 set_mu_type &= ~0x05; // unset bit 0, 2
11281 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11282 set_mu_type |= 0x01;
11283 set_mu_type &= ~0x04;
11284 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11285 set_mu_type &= ~0x01;
11286 set_mu_type |= 0x04;
11287 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11288 set_mu_type |= 0x05; // set bit 0, 2
11289 }
11290
developera7149722023-01-11 11:36:21 +080011291 new_vendor_patch = check_is_hemu_vendor_new_patch();
11292 if (new_vendor_patch)
11293 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11294 else
11295 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11296
11297 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011298 sprintf(buf, "%u", set_mu_type);
11299 params.value = buf;
11300 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11301 wifi_hostapdWrite(config_file, &params, 1);
11302 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011303 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011304
11305 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11306 return RETURN_OK;
11307}
11308
11309INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11310{
11311 struct params params={0};
11312 char config_file[64] = {0};
11313 char buf[64] = {0};
11314 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011315 bool new_vendor_patch = FALSE;
11316 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011317
11318 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11319
11320 if (mu_type == NULL)
11321 return RETURN_ERR;
11322
developera7149722023-01-11 11:36:21 +080011323 new_vendor_patch = check_is_hemu_vendor_new_patch();
11324
11325 if (new_vendor_patch)
11326 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11327 else
11328 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11329
developer3e6b1692022-09-30 18:04:05 +080011330 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011331 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011332 get_mu_type = strtol(buf, NULL, 10);
11333
11334 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11335 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11336 else if (get_mu_type & 0x04)
11337 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11338 else if (get_mu_type & 0x01)
11339 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11340 else
11341 *mu_type = WIFI_DL_MU_TYPE_NONE;
11342
11343 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11344 return RETURN_OK;
11345}
11346
11347INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11348{
11349 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11350 struct params params={0};
11351 char config_file[64] = {0};
11352 char buf[64] = {0};
11353 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011354 bool new_vendor_patch = FALSE;
11355 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11357
developera7149722023-01-11 11:36:21 +080011358 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011359
11360 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11361 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11362 set_mu_type &= ~0x0a;
11363 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11364 set_mu_type |= 0x02;
11365 set_mu_type &= ~0x08;
11366 }
11367
developera7149722023-01-11 11:36:21 +080011368 new_vendor_patch = check_is_hemu_vendor_new_patch();
11369
11370 if (new_vendor_patch)
11371 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11372 else
11373 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11374
11375 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011376 sprintf(buf, "%u", set_mu_type);
11377 params.value = buf;
11378 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11379 wifi_hostapdWrite(config_file, &params, 1);
11380 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011381 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011382
11383 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11384 return RETURN_OK;
11385}
11386
11387INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11388{
11389 struct params params={0};
11390 char config_file[64] = {0};
11391 char buf[64] = {0};
11392 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011393 bool new_vendor_patch = FALSE;
11394 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011395
11396 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11397
developera7149722023-01-11 11:36:21 +080011398 new_vendor_patch = check_is_hemu_vendor_new_patch();
11399
11400 if (new_vendor_patch)
11401 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11402 else
11403 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11404
developer3e6b1692022-09-30 18:04:05 +080011405 if (mu_type == NULL)
11406 return RETURN_ERR;
11407
11408 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011409 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011410
11411 get_mu_type = strtol(buf, NULL, 10);
11412 if (get_mu_type & 0x02)
11413 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11414 else
11415 *mu_type = WIFI_DL_MU_TYPE_NONE;
11416
11417 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11418 return RETURN_OK;
11419}
11420
11421
developer454b9462022-09-13 15:29:16 +080011422INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11423{
11424 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011425 char buf[256] = {0};
11426 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011427 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011428 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011429 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011430 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011431
11432 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11433
developer254882b2022-09-30 17:12:31 +080011434 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011435 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11436 return RETURN_ERR;
11437 }
developer454b9462022-09-13 15:29:16 +080011438
developer254882b2022-09-30 17:12:31 +080011439 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011440 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011441
developer254882b2022-09-30 17:12:31 +080011442 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11443 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011444 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011445 _syscmd(cmd, buf, sizeof(buf));
11446 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11447 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11448 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011449 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 +080011450 _syscmd(cmd, buf, sizeof(buf));
11451 }
11452 if (band == band_5) {
11453 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11454 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011455 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 +080011456 _syscmd(cmd, buf, sizeof(buf));
11457 }
11458 }
11459 }
11460 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011461
developer254882b2022-09-30 17:12:31 +080011462 if (guard_interval == wifi_guard_interval_400)
11463 strcpy(GI, "0.4");
11464 else if (guard_interval == wifi_guard_interval_800)
11465 strcpy(GI, "0.8");
11466 else if (guard_interval == wifi_guard_interval_1600)
11467 strcpy(GI, "1.6");
11468 else if (guard_interval == wifi_guard_interval_3200)
11469 strcpy(GI, "3.2");
11470 else if (guard_interval == wifi_guard_interval_auto)
11471 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011472 // Record GI for get GI function
11473 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11474 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011475 if (f == NULL)
11476 return RETURN_ERR;
11477 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011478 fclose(f);
11479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11480 return RETURN_OK;
11481}
11482
11483INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11484{
11485 char buf[32] = {0};
11486 char cmd[64] = {0};
11487
11488 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11489
11490 if (guard_interval == NULL)
11491 return RETURN_ERR;
11492
developer7c4cd202023-03-01 10:56:29 +080011493 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011494 _syscmd(cmd, buf, sizeof(buf));
11495
11496 if (strncmp(buf, "0.4", 3) == 0)
11497 *guard_interval = wifi_guard_interval_400;
11498 else if (strncmp(buf, "0.8", 3) == 0)
11499 *guard_interval = wifi_guard_interval_800;
11500 else if (strncmp(buf, "1.6", 3) == 0)
11501 *guard_interval = wifi_guard_interval_1600;
11502 else if (strncmp(buf, "3.2", 3) == 0)
11503 *guard_interval = wifi_guard_interval_3200;
11504 else
11505 *guard_interval = wifi_guard_interval_auto;
11506
11507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11508 return RETURN_OK;
11509}
11510
developer3cc61d12022-09-13 16:36:05 +080011511INT wifi_setBSSColor(INT radio_index, UCHAR color)
11512{
11513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11514 struct params params = {0};
11515 char config_file[128] = {0};
11516 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011517 UCHAR *color_list;
11518 int color_num = 0;
11519 int maxNumberColors = 64;
11520 BOOL color_is_aval = FALSE;
11521
developerbf0b9dc2023-07-06 14:30:54 +080011522 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011523 return RETURN_ERR;
11524
developer517f3be2023-05-08 10:02:39 +080011525 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11526 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11527 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011528 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011529 }
developer2acb9632023-03-14 14:58:31 +080011530
11531 for (int i = 0; i < color_num; i++) {
11532 if (color_list[i] == color) {
11533 color_is_aval = TRUE;
11534 break;
11535 }
11536 }
11537 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011538 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011539 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11540 return RETURN_ERR;
11541 }
developer3cc61d12022-09-13 16:36:05 +080011542
11543 params.name = "he_bss_color";
11544 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11545 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011546 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011547 wifi_hostapdWrite(config_file, &params, 1);
11548 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011549 wifi_reloadAp(radio_index);
11550
developer517f3be2023-05-08 10:02:39 +080011551 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011552 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11553 return RETURN_OK;
11554}
11555
11556INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11557{
developer3cc61d12022-09-13 16:36:05 +080011558 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011559 char cmd[128] = {0};
11560 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011561
developer3cc61d12022-09-13 16:36:05 +080011562 if (NULL == color)
11563 return RETURN_ERR;
11564
developer2acb9632023-03-14 14:58:31 +080011565 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11566 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011567
developer2acb9632023-03-14 14:58:31 +080011568 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11569 _syscmd(cmd, buf, sizeof(buf));
11570 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011571
developer2acb9632023-03-14 14:58:31 +080011572 return RETURN_OK;
11573}
11574
11575INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11576{
11577 char buf[64] = {0};
11578 char cmd[128] = {0};
11579 char interface_name[16] = {0};
11580 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011581
developer2acb9632023-03-14 14:58:31 +080011582 if (NULL == colorList || NULL == numColorReturned)
11583 return RETURN_ERR;
11584
11585 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11586 return RETURN_ERR;
11587
11588 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11589 _syscmd(cmd, buf, sizeof(buf));
11590 color_bitmap = strtoull(buf, NULL, 16);
11591
11592 *numColorReturned = 0;
11593 for (int i = 0; i < maxNumberColors; i++) {
11594 if (color_bitmap & 1) {
11595 colorList[*numColorReturned] = i;
11596 (*numColorReturned) += 1;
11597 }
11598 color_bitmap >>= 1;
11599 }
developer3cc61d12022-09-13 16:36:05 +080011600 return RETURN_OK;
11601}
11602
developer06a01d92022-09-07 16:32:39 +080011603/* multi-psk support */
11604INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11605{
11606 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011607 char interface_name[16] = {0};
11608
developerac6f1142022-12-20 19:26:35 +080011609 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011610 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011611
developerd946fd62022-12-08 18:03:28 +080011612 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11613 interface_name,
developer06a01d92022-09-07 16:32:39 +080011614 mac[0],
11615 mac[1],
11616 mac[2],
11617 mac[3],
11618 mac[4],
11619 mac[5]
11620 );
11621 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11622 _syscmd(cmd, key->wifi_keyId, 64);
11623
11624
11625 return RETURN_OK;
11626}
11627
11628INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11629{
developerd946fd62022-12-08 18:03:28 +080011630 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011631 FILE *fd = NULL;
11632 char fname[100];
11633 char cmd[128] = {0};
11634 char out[64] = {0};
11635 wifi_key_multi_psk_t * key = NULL;
11636 if(keysNumber < 0)
11637 return RETURN_ERR;
11638
developer431128d2022-12-16 15:30:41 +080011639 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011640 fd = fopen(fname, "w");
11641 if (!fd) {
11642 return RETURN_ERR;
11643 }
11644 key= (wifi_key_multi_psk_t *) keys;
11645 for(int i=0; i<keysNumber; ++i, key++) {
11646 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11647 }
11648 fclose(fd);
11649
11650 //reload file
developerac6f1142022-12-20 19:26:35 +080011651 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011652 return RETURN_ERR;
11653 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011654 _syscmd(cmd, out, 64);
11655 return RETURN_OK;
11656}
11657
11658INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11659{
11660 FILE *fd = NULL;
11661 char fname[100];
11662 char * line = NULL;
11663 char * pos = NULL;
11664 size_t len = 0;
11665 ssize_t read = 0;
11666 INT ret = RETURN_OK;
11667 wifi_key_multi_psk_t *keys_it = NULL;
11668
11669 if (keysNumber < 1) {
11670 return RETURN_ERR;
11671 }
11672
developer431128d2022-12-16 15:30:41 +080011673 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011674 fd = fopen(fname, "r");
11675 if (!fd) {
11676 return RETURN_ERR;
11677 }
11678
11679 if (keys == NULL) {
11680 ret = RETURN_ERR;
11681 goto close;
11682 }
11683
11684 keys_it = keys;
11685 while ((read = getline(&line, &len, fd)) != -1) {
11686 //Strip trailing new line if present
11687 if (read > 0 && line[read-1] == '\n') {
11688 line[read-1] = '\0';
11689 }
11690
11691 if(strcmp(line,"keyid=")) {
11692 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11693 if (!(pos = index(line, ' '))) {
11694 ret = RETURN_ERR;
11695 goto close;
11696 }
11697 pos++;
11698 //Here should be 00:00:00:00:00:00
11699 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11700 printf("Not supported MAC: %s\n", pos);
11701 }
11702 if (!(pos = index(pos, ' '))) {
11703 ret = RETURN_ERR;
11704 goto close;
11705 }
11706 pos++;
11707
11708 //The rest is PSK
11709 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11710 keys_it++;
11711
11712 if(--keysNumber <= 0)
11713 break;
11714 }
11715 }
11716
11717close:
11718 free(line);
11719 fclose(fd);
11720 return ret;
11721}
11722/* end of multi-psk support */
11723
11724INT wifi_setNeighborReports(UINT apIndex,
11725 UINT numNeighborReports,
11726 wifi_NeighborReport_t *neighborReports)
11727{
11728 char cmd[256] = { 0 };
11729 char hex_bssid[13] = { 0 };
11730 char bssid[18] = { 0 };
11731 char nr[256] = { 0 };
11732 char ssid[256];
11733 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011734 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011735 INT ret;
11736
11737 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011738 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011739 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011740 return RETURN_ERR;
11741 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 +080011742 system(cmd);
11743
11744 for(unsigned int i = 0; i < numNeighborReports; i++)
11745 {
11746 memset(ssid, 0, sizeof(ssid));
11747 ret = wifi_getSSIDName(apIndex, ssid);
11748 if (ret != RETURN_OK)
11749 return RETURN_ERR;
11750
11751 memset(hex_ssid, 0, sizeof(hex_ssid));
11752 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11753 sprintf(hex_ssid + k,"%02x", ssid[j]);
11754
11755 snprintf(hex_bssid, sizeof(hex_bssid),
11756 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11757 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11758 snprintf(bssid, sizeof(bssid),
11759 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11760 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11761
11762 snprintf(nr, sizeof(nr),
11763 "%s" // bssid
11764 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11765 "%02hhx" // operclass
11766 "%02hhx" // channel
11767 "%02hhx", // phy_mode
11768 hex_bssid,
11769 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11770 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11771 neighborReports[i].opClass,
11772 neighborReports[i].channel,
11773 neighborReports[i].phyTable);
11774
11775 snprintf(cmd, sizeof(cmd),
11776 "hostapd_cli set_neighbor "
11777 "%s " // bssid
11778 "ssid=%s " // ssid
11779 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011780 "-i %s",
11781 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011782
11783 if (WEXITSTATUS(system(cmd)) != 0)
11784 {
11785 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11786 }
11787 }
11788
11789 return RETURN_OK;
11790}
11791
11792INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11793{
11794 return RETURN_OK;
11795}
11796
11797#ifdef _WIFI_HAL_TEST_
11798int main(int argc,char **argv)
11799{
11800 int index;
11801 INT ret=0;
11802 char buf[1024]="";
11803
11804 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11805 if(argc<3)
11806 {
11807 if(argc==2)
11808 {
11809 if(!strcmp(argv[1], "init"))
11810 return wifi_init();
11811 if(!strcmp(argv[1], "reset"))
11812 return wifi_reset();
11813 if(!strcmp(argv[1], "wifi_getHalVersion"))
11814 {
11815 char buffer[64];
11816 if(wifi_getHalVersion(buffer)==RETURN_OK)
11817 printf("Version: %s\n", buffer);
11818 else
11819 printf("Error in wifi_getHalVersion\n");
11820 return RETURN_OK;
11821 }
11822 }
11823 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11824 exit(-1);
11825 }
11826
11827 index = atoi(argv[2]);
11828 if(strstr(argv[1], "wifi_getApName")!=NULL)
11829 {
11830 wifi_getApName(index,buf);
11831 printf("Ap name is %s \n",buf);
11832 return 0;
11833 }
11834 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11835 {
11836 BOOL b = FALSE;
11837 BOOL *output_bool = &b;
11838 wifi_getRadioAutoChannelEnable(index,output_bool);
11839 printf("Channel enabled = %d \n",b);
11840 return 0;
11841 }
11842 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11843 {
11844 wifi_getApWpaEncryptionMode(index,buf);
11845 printf("encryption enabled = %s\n",buf);
11846 return 0;
11847 }
11848 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11849 {
11850 BOOL b = FALSE;
11851 BOOL *output_bool = &b;
11852 wifi_getApSsidAdvertisementEnable(index,output_bool);
11853 printf("advertisment enabled = %d\n",b);
11854 return 0;
11855 }
11856 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11857 {
11858 if(argc <= 3 )
11859 {
11860 printf("Insufficient arguments \n");
11861 exit(-1);
11862 }
11863
11864 char sta[20] = {'\0'};
11865 ULLONG handle= 0;
11866 strcpy(sta,argv[3]);
11867 mac_address_t st;
11868 mac_addr_aton(st,sta);
11869
11870 wifi_associated_dev_tid_stats_t tid_stats;
11871 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11872 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11873 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);
11874 }
11875
11876 if(strstr(argv[1], "getApEnable")!=NULL) {
11877 BOOL enable;
11878 ret=wifi_getApEnable(index, &enable);
11879 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11880 }
11881 else if(strstr(argv[1], "setApEnable")!=NULL) {
11882 BOOL enable = atoi(argv[3]);
11883 ret=wifi_setApEnable(index, enable);
11884 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11885 }
11886 else if(strstr(argv[1], "getApStatus")!=NULL) {
11887 char status[64];
11888 ret=wifi_getApStatus(index, status);
11889 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11890 }
11891 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11892 {
11893 wifi_getSSIDNameStatus(index,buf);
11894 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11895 return 0;
11896 }
11897 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11898 wifi_ssidTrafficStats2_t stats={0};
11899 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11900 printf("%s %d: returns %d\n", argv[1], index, ret);
11901 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11902 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11903 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11904 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11905 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11906 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11907 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11908 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11909 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11910 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11911 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11912 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11913 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11914 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11915 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11916 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11917 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11918 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11919 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11920 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11921 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11922 }
11923 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11924 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11925 UINT array_size=0;
11926 UINT i=0;
11927 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11928 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11929 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11930 printf(" neighbor %d:\n", i);
11931 printf(" ap_SSID =%s\n", pt->ap_SSID);
11932 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11933 printf(" ap_Mode =%s\n", pt->ap_Mode);
11934 printf(" ap_Channel =%d\n", pt->ap_Channel);
11935 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11936 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11937 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11938 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11939 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11940 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11941 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11942 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11943 printf(" ap_Noise =%d\n", pt->ap_Noise);
11944 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11945 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11946 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11947 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11948 }
11949 if(neighbor_ap_array)
11950 free(neighbor_ap_array); //make sure to free the list
11951 }
11952 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11953 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11954 UINT array_size=0;
11955 UINT i=0;
11956 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11957 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11958 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11959 printf(" associated_dev %d:\n", i);
11960 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11961 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11962 printf(" cli_SNR =%d\n", pt->cli_SNR);
11963 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11964 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11965 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11966 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11967 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11968 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11969 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11970 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11971 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11972 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11973 }
11974 if(associated_dev_array)
11975 free(associated_dev_array); //make sure to free the list
11976 }
11977
11978 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11979 {
11980#define MAX_ARRAY_SIZE 64
11981 int i, array_size;
11982 char *p, *ch_str;
11983 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11984
11985 if(argc != 5)
11986 {
11987 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11988 exit(-1);
11989 }
11990 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11991
11992 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11993 {
11994 strtok_r(ch_str, ",", &p);
11995 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11996 }
11997 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11998 if(!array_size)
11999 array_size=1;//Need to print current channel statistics
12000 for(i=0; i<array_size; i++)
12001 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12002 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12003 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12004 input_output_channelStats_array[i].ch_number,\
12005 input_output_channelStats_array[i].ch_noise,\
12006 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12007 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12008 input_output_channelStats_array[i].ch_utilization_busy,\
12009 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12010 input_output_channelStats_array[i].ch_utilization_total);
12011 }
12012
12013 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12014 {
12015 if(argc <= 3 )
12016 {
12017 printf("Insufficient arguments \n");
12018 exit(-1);
12019 }
12020 char mac_addr[20] = {'\0'};
12021 wifi_device_t output_struct;
12022 int dev_index = atoi(argv[3]);
12023
12024 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12025 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12026 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);
12027 }
12028
12029 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12030 {
12031 if (argc <= 3)
12032 {
12033 printf("Insufficient arguments\n");
12034 exit(-1);
12035 }
12036 char args[256];
12037 wifi_NeighborReport_t *neighborReports;
12038
12039 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12040 if (!neighborReports)
12041 {
12042 printf("Failed to allocate memory");
12043 exit(-1);
12044 }
12045
12046 for (int i = 3; i < argc; ++i)
12047 {
12048 char *val;
12049 int j = 0;
12050 memset(args, 0, sizeof(args));
12051 strncpy(args, argv[i], sizeof(args));
12052 val = strtok(args, ";");
12053 while (val != NULL)
12054 {
12055 if (j == 0)
12056 {
12057 mac_addr_aton(neighborReports[i - 3].bssid, val);
12058 } else if (j == 1)
12059 {
12060 neighborReports[i - 3].info = strtol(val, NULL, 16);
12061 } else if (j == 2)
12062 {
12063 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12064 } else if (j == 3)
12065 {
12066 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12067 } else if (j == 4)
12068 {
12069 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12070 } else {
12071 printf("Insufficient arguments]n\n");
12072 exit(-1);
12073 }
12074 val = strtok(NULL, ";");
12075 j++;
12076 }
12077 }
12078
12079 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12080 if (ret != RETURN_OK)
12081 {
12082 printf("wifi_setNeighborReports ret = %d", ret);
12083 exit(-1);
12084 }
12085 }
12086 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12087 {
12088 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12089 printf("%s.\n", buf);
12090 else
12091 printf("Error returned\n");
12092 }
12093 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12094 {
12095 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12096 printf("%s.\n", buf);
12097 else
12098 printf("Error returned\n");
12099 }
12100 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12101 {
12102 if (argc <= 2)
12103 {
12104 printf("Insufficient arguments\n");
12105 exit(-1);
12106 }
12107 char buf[64]= {'\0'};
12108 wifi_getRadioOperatingChannelBandwidth(index,buf);
12109 printf("Current bandwidth is %s \n",buf);
12110 return 0;
12111 }
12112 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12113 {
12114 if (argc <= 5)
12115 {
12116 printf("Insufficient arguments\n");
12117 exit(-1);
12118 }
12119 UINT channel = atoi(argv[3]);
12120 UINT width = atoi(argv[4]);
12121 UINT beacon = atoi(argv[5]);
12122 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12123 printf("Result = %d", ret);
12124 }
12125
12126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12127 return 0;
12128}
12129
12130#endif
12131
12132#ifdef WIFI_HAL_VERSION_3
12133
developer1e5aa162022-09-13 16:06:24 +080012134INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12135{
12136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12137 if (bitMap & WIFI_BITRATE_1MBPS)
12138 strcat(BasicRate, "1,");
12139 if (bitMap & WIFI_BITRATE_2MBPS)
12140 strcat(BasicRate, "2,");
12141 if (bitMap & WIFI_BITRATE_5_5MBPS)
12142 strcat(BasicRate, "5.5,");
12143 if (bitMap & WIFI_BITRATE_6MBPS)
12144 strcat(BasicRate, "6,");
12145 if (bitMap & WIFI_BITRATE_9MBPS)
12146 strcat(BasicRate, "9,");
12147 if (bitMap & WIFI_BITRATE_11MBPS)
12148 strcat(BasicRate, "11,");
12149 if (bitMap & WIFI_BITRATE_12MBPS)
12150 strcat(BasicRate, "12,");
12151 if (bitMap & WIFI_BITRATE_18MBPS)
12152 strcat(BasicRate, "18,");
12153 if (bitMap & WIFI_BITRATE_24MBPS)
12154 strcat(BasicRate, "24,");
12155 if (bitMap & WIFI_BITRATE_36MBPS)
12156 strcat(BasicRate, "36,");
12157 if (bitMap & WIFI_BITRATE_48MBPS)
12158 strcat(BasicRate, "48,");
12159 if (bitMap & WIFI_BITRATE_54MBPS)
12160 strcat(BasicRate, "54,");
12161 if (strlen(BasicRate) != 0) // remove last comma
12162 BasicRate[strlen(BasicRate) - 1] = '\0';
12163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12164 return RETURN_OK;
12165}
12166
12167INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12168{
12169 UINT BitMap = 0;
12170 char *rate;
12171
12172 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12173 rate = strtok(BasicRatesList, ",");
12174 while(rate != NULL)
12175 {
12176 if (strcmp(rate, "1") == 0)
12177 BitMap |= WIFI_BITRATE_1MBPS;
12178 else if (strcmp(rate, "2") == 0)
12179 BitMap |= WIFI_BITRATE_2MBPS;
12180 else if (strcmp(rate, "5.5") == 0)
12181 BitMap |= WIFI_BITRATE_5_5MBPS;
12182 else if (strcmp(rate, "6") == 0)
12183 BitMap |= WIFI_BITRATE_6MBPS;
12184 else if (strcmp(rate, "9") == 0)
12185 BitMap |= WIFI_BITRATE_9MBPS;
12186 else if (strcmp(rate, "11") == 0)
12187 BitMap |= WIFI_BITRATE_11MBPS;
12188 else if (strcmp(rate, "12") == 0)
12189 BitMap |= WIFI_BITRATE_12MBPS;
12190 else if (strcmp(rate, "18") == 0)
12191 BitMap |= WIFI_BITRATE_18MBPS;
12192 else if (strcmp(rate, "24") == 0)
12193 BitMap |= WIFI_BITRATE_24MBPS;
12194 else if (strcmp(rate, "36") == 0)
12195 BitMap |= WIFI_BITRATE_36MBPS;
12196 else if (strcmp(rate, "48") == 0)
12197 BitMap |= WIFI_BITRATE_48MBPS;
12198 else if (strcmp(rate, "54") == 0)
12199 BitMap |= WIFI_BITRATE_54MBPS;
12200 rate = strtok(NULL, ",");
12201 }
12202 *basicRateBitMap = BitMap;
12203 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12204 return RETURN_OK;
12205}
12206
developer7c4cd202023-03-01 10:56:29 +080012207INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12208{
12209 int center_channel = 0;
12210 char central_channel_str[16] = {0};
12211 char config_file[32] = {0};
12212 struct params param = {0};
12213
12214 center_channel = util_unii_6g_centerfreq("HT320", channel);
12215 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12216 if (channel >= 193)
12217 return RETURN_ERR;
12218 if (channel >= 33) {
12219 if (channel > center_channel)
12220 center_channel += 32;
12221 else
12222 center_channel -= 32;
12223 }
12224 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12225 if (channel <= 29)
12226 return RETURN_ERR;
12227 }
12228 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12229 param.name = "eht_oper_centr_freq_seg0_idx";
12230 param.value = central_channel_str;
12231 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12232 wifi_hostapdWrite(config_file, &param, 1);
12233
12234 return RETURN_OK;
12235}
12236
12237INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12238{
12239 int op_class = 0;
12240 char config_file[32] = {0};
12241 char op_class_str[8] = {0};
12242 struct params param = {0};
12243
12244 if (bandwidth == 20)
12245 op_class = 131;
12246 else if (bandwidth == 40)
12247 op_class = 132;
12248 else if (bandwidth == 80)
12249 op_class = 133;
12250 else if (bandwidth == 160)
12251 op_class = 134;
12252 else if (bandwidth == 320)
12253 op_class = 137;
12254 else
12255 return RETURN_ERR;
12256 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12257 param.name = "op_class";
12258 param.value = op_class_str;
12259 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12260 wifi_hostapdWrite(config_file, &param, 1);
12261 return RETURN_OK;
12262}
12263
12264INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12265{
12266 char config_file[32] = {0};
12267 char buf [16] = {0};
12268
12269 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12270 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12271 return RETURN_ERR; // 6g band should set op_class
12272 *class = (UINT)strtoul(buf, NULL, 10);
12273
12274 return RETURN_OK;
12275}
12276
developer1e5aa162022-09-13 16:06:24 +080012277// 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 +080012278INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12279{
developer1e5aa162022-09-13 16:06:24 +080012280 char buf[128] = {0};
12281 char cmd[128] = {0};
12282 char config_file[64] = {0};
12283 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012284 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012285 wifi_radio_operationParam_t current_param;
12286
12287 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12288
12289 multiple_set = TRUE;
12290 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12291 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12292 return RETURN_ERR;
12293 }
12294 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12295 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12296 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12297 return RETURN_ERR;
12298 }
12299 }
developer5884e982022-10-06 10:52:50 +080012300
12301 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12302 bandwidth = 20;
12303 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12304 bandwidth = 40;
12305 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12306 bandwidth = 80;
12307 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12308 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012309 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12310 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012311 if (operationParam->autoChannelEnabled){
12312 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12313 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12314 return RETURN_ERR;
12315 }
12316 }else{
developer1e5aa162022-09-13 16:06:24 +080012317 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12318 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12319 return RETURN_ERR;
12320 }
12321 }
developer5884e982022-10-06 10:52:50 +080012322
developer7c4cd202023-03-01 10:56:29 +080012323 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12324 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12325 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12326 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12327 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12328 return RETURN_ERR;
12329 }
12330 }
12331
12332 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12333 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12334 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12335 return RETURN_ERR;
12336 }
12337 }
12338
developer1e5aa162022-09-13 16:06:24 +080012339 if (current_param.variant != operationParam->variant) {
12340 // Two different definition bit map, so need to check every bit.
12341 if (operationParam->variant & WIFI_80211_VARIANT_A)
12342 set_mode |= WIFI_MODE_A;
12343 if (operationParam->variant & WIFI_80211_VARIANT_B)
12344 set_mode |= WIFI_MODE_B;
12345 if (operationParam->variant & WIFI_80211_VARIANT_G)
12346 set_mode |= WIFI_MODE_G;
12347 if (operationParam->variant & WIFI_80211_VARIANT_N)
12348 set_mode |= WIFI_MODE_N;
12349 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12350 set_mode |= WIFI_MODE_AC;
12351 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12352 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012353 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12354 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012355 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12356 memset(buf, 0, sizeof(buf));
12357 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12358 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12359 return RETURN_ERR;
12360 }
12361 }
12362 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12363 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12364 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12365 return RETURN_ERR;
12366 }
12367 }
12368 if (current_param.beaconInterval != operationParam->beaconInterval) {
12369 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12370 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12371 return RETURN_ERR;
12372 }
12373 }
12374 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12375 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12376 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12377 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12378 return RETURN_ERR;
12379 }
12380 }
12381 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12382 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12383 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12384 return RETURN_ERR;
12385 }
12386 }
12387 if (current_param.guardInterval != operationParam->guardInterval) {
12388 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12389 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12390 return RETURN_ERR;
12391 }
12392 }
12393 if (current_param.transmitPower != operationParam->transmitPower) {
12394 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12395 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12396 return RETURN_ERR;
12397 }
12398 }
12399 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12400 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12401 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12402 return RETURN_ERR;
12403 }
12404 }
12405 if (current_param.obssCoex != operationParam->obssCoex) {
12406 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12407 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12408 return RETURN_ERR;
12409 }
12410 }
12411 if (current_param.stbcEnable != operationParam->stbcEnable) {
12412 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12413 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12414 return RETURN_ERR;
12415 }
12416 }
developer5735d092023-09-19 20:12:26 +080012417 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12418 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12419 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12420 return RETURN_ERR;
12421 }
12422 }
developer1e5aa162022-09-13 16:06:24 +080012423
12424 // if enable is true, then restart the radio
12425 wifi_setRadioEnable(index, FALSE);
12426 if (operationParam->enable == TRUE)
12427 wifi_setRadioEnable(index, TRUE);
12428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12429
developer06a01d92022-09-07 16:32:39 +080012430 return RETURN_OK;
12431}
12432
12433INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12434{
developer1e5aa162022-09-13 16:06:24 +080012435 char band[64] = {0};
12436 char buf[256] = {0};
12437 char config_file[64] = {0};
12438 char cmd[128] = {0};
12439 int ret = RETURN_ERR;
12440 int mode = 0;
12441 ULONG channel = 0;
12442 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012443
12444 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12445 printf("Entering %s index = %d\n", __func__, (int)index);
12446
developer1e5aa162022-09-13 16:06:24 +080012447 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12448 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12449 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012450 {
developer1e5aa162022-09-13 16:06:24 +080012451 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012452 return RETURN_ERR;
12453 }
12454 operationParam->enable = enabled;
12455
12456 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012457 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012458 {
developer1e5aa162022-09-13 16:06:24 +080012459 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012460 return RETURN_ERR;
12461 }
12462
12463 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012464 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012465 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012466 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012467 else if (!strcmp(band, "6GHz"))
12468 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012469 else
12470 {
developer1e5aa162022-09-13 16:06:24 +080012471 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012472 band);
12473 }
12474
developer1e5aa162022-09-13 16:06:24 +080012475 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12476 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12477 operationParam->channel = 0;
12478 operationParam->autoChannelEnabled = TRUE;
12479 } else {
12480 operationParam->channel = strtol(buf, NULL, 10);
12481 operationParam->autoChannelEnabled = FALSE;
12482 }
12483
developer06a01d92022-09-07 16:32:39 +080012484 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012485 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12486 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12487 return RETURN_ERR;
12488 }
developer06a01d92022-09-07 16:32:39 +080012489 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12490 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12491 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012492 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012493 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12494 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012495 else
12496 {
developer1e5aa162022-09-13 16:06:24 +080012497 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12498 return false;
developer06a01d92022-09-07 16:32:39 +080012499 }
12500
developer7c4cd202023-03-01 10:56:29 +080012501 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12502 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12503 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12504 return RETURN_ERR;
12505 }
12506 }
12507
developer1e5aa162022-09-13 16:06:24 +080012508 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12509 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12510 return RETURN_ERR;
12511 }
12512 // Two different definition bit map, so need to check every bit.
12513 if (mode & WIFI_MODE_A)
12514 operationParam->variant |= WIFI_80211_VARIANT_A;
12515 if (mode & WIFI_MODE_B)
12516 operationParam->variant |= WIFI_80211_VARIANT_B;
12517 if (mode & WIFI_MODE_G)
12518 operationParam->variant |= WIFI_80211_VARIANT_G;
12519 if (mode & WIFI_MODE_N)
12520 operationParam->variant |= WIFI_80211_VARIANT_N;
12521 if (mode & WIFI_MODE_AC)
12522 operationParam->variant |= WIFI_80211_VARIANT_AC;
12523 if (mode & WIFI_MODE_AX)
12524 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012525 if (mode & WIFI_MODE_BE)
12526 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012527 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12528 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12529 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012530 }
developer1e5aa162022-09-13 16:06:24 +080012531 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12532 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12533 return RETURN_ERR;
12534 }
12535 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12536 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12537 return RETURN_ERR;
12538 }
developer06a01d92022-09-07 16:32:39 +080012539
developer1e5aa162022-09-13 16:06:24 +080012540 memset(buf, 0, sizeof(buf));
12541 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12542 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12543 return RETURN_ERR;
12544 }
12545 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12546
12547 memset(buf, 0, sizeof(buf));
12548 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12549 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12550 return RETURN_ERR;
12551 }
12552 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12553
12554 memset(buf, 0, sizeof(buf));
12555 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12556 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12557
12558 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12559 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12560 return RETURN_ERR;
12561 }
12562 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12563 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12564 return RETURN_ERR;
12565 }
12566
12567 memset(buf, 0, sizeof(buf));
12568 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12569 if (strcmp(buf, "-1") == 0) {
12570 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12571 operationParam->ctsProtection = FALSE;
12572 } else {
12573 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12574 operationParam->ctsProtection = TRUE;
12575 }
12576
12577 memset(buf, 0, sizeof(buf));
12578 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12579 if (strcmp(buf, "0") == 0)
12580 operationParam->obssCoex = FALSE;
12581 else
12582 operationParam->obssCoex = TRUE;
12583
12584 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12585 _syscmd(cmd, buf, sizeof(buf));
12586 if (strlen(buf) != 0)
12587 operationParam->stbcEnable = TRUE;
12588 else
12589 operationParam->stbcEnable = FALSE;
12590
developer5735d092023-09-19 20:12:26 +080012591 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12592 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12593 return RETURN_ERR;
12594 }
developer1e5aa162022-09-13 16:06:24 +080012595
12596 // Below value is hardcoded
12597
12598 operationParam->numSecondaryChannels = 0;
12599 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12600 operationParam->channelSecondary[i] = 0;
12601 }
12602 operationParam->csa_beacon_count = 15;
12603 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012604
12605 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12606 return RETURN_OK;
12607}
12608
12609static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12610{
developerc086fb72022-10-04 10:18:22 +080012611 int max_radio_num = 0;
12612
12613 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012614 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012615 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12616 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012617 }
12618
developerc086fb72022-10-04 10:18:22 +080012619 return (arrayIndex * max_radio_num) + radioIndex;
12620}
developer06a01d92022-09-07 16:32:39 +080012621
developerc086fb72022-10-04 10:18:22 +080012622wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12623 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12624 return WIFI_BITRATE_1MBPS;
12625 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12626 return WIFI_BITRATE_2MBPS;
12627 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12628 return WIFI_BITRATE_5_5MBPS;
12629 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12630 return WIFI_BITRATE_6MBPS;
12631 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12632 return WIFI_BITRATE_9MBPS;
12633 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12634 return WIFI_BITRATE_11MBPS;
12635 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12636 return WIFI_BITRATE_12MBPS;
12637 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12638 return WIFI_BITRATE_18MBPS;
12639 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12640 return WIFI_BITRATE_24MBPS;
12641 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12642 return WIFI_BITRATE_36MBPS;
12643 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12644 return WIFI_BITRATE_48MBPS;
12645 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12646 return WIFI_BITRATE_54MBPS;
12647 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012648}
12649
developer1d57d002022-10-12 18:03:15 +080012650INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12651{
12652 if (beacon == WIFI_BITRATE_1MBPS)
12653 strcpy(beacon_str, "1Mbps");
12654 else if (beacon == WIFI_BITRATE_2MBPS)
12655 strcpy(beacon_str, "2Mbps");
12656 else if (beacon == WIFI_BITRATE_5_5MBPS)
12657 strcpy(beacon_str, "5.5Mbps");
12658 else if (beacon == WIFI_BITRATE_6MBPS)
12659 strcpy(beacon_str, "6Mbps");
12660 else if (beacon == WIFI_BITRATE_9MBPS)
12661 strcpy(beacon_str, "9Mbps");
12662 else if (beacon == WIFI_BITRATE_11MBPS)
12663 strcpy(beacon_str, "11Mbps");
12664 else if (beacon == WIFI_BITRATE_12MBPS)
12665 strcpy(beacon_str, "12Mbps");
12666 else if (beacon == WIFI_BITRATE_18MBPS)
12667 strcpy(beacon_str, "18Mbps");
12668 else if (beacon == WIFI_BITRATE_24MBPS)
12669 strcpy(beacon_str, "24Mbps");
12670 else if (beacon == WIFI_BITRATE_36MBPS)
12671 strcpy(beacon_str, "36Mbps");
12672 else if (beacon == WIFI_BITRATE_48MBPS)
12673 strcpy(beacon_str, "48Mbps");
12674 else if (beacon == WIFI_BITRATE_54MBPS)
12675 strcpy(beacon_str, "54Mbps");
12676 return RETURN_OK;
12677}
12678
developer74ed4192023-09-21 17:15:17 +080012679void checkVapStatus(int apIndex, bool *enable)
12680{
12681 char if_name[16] = {0};
12682 char cmd[128] = {0};
12683 char buf[128] = {0};
12684
12685 *enable = FALSE;
12686 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12687 return;
12688
12689 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12690 _syscmd(cmd, buf, sizeof(buf));
12691 if (strlen(buf) > 0)
12692 *enable = TRUE;
12693 return;
12694}
12695
developer06a01d92022-09-07 16:32:39 +080012696INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12697{
developerc086fb72022-10-04 10:18:22 +080012698 INT mode = 0;
12699 INT ret = -1;
12700 INT output = 0;
12701 int i = 0;
12702 int vap_index = 0;
12703 BOOL enabled = FALSE;
12704 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012705 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012706
developer06a01d92022-09-07 16:32:39 +080012707
12708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12709 printf("Entering %s index = %d\n", __func__, (int)index);
12710
developera77d84b2023-02-22 16:10:50 +080012711 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012712 {
developerc086fb72022-10-04 10:18:22 +080012713 map->vap_array[i].radio_index = index;
12714
developer06a01d92022-09-07 16:32:39 +080012715 vap_index = array_index_to_vap_index(index, i);
12716 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012717 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012718
developerc086fb72022-10-04 10:18:22 +080012719 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012720
12721 map->vap_array[i].vap_index = vap_index;
12722
12723 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012724 ret = wifi_getApName(vap_index, buf);
12725 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012726 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12727
developerc086fb72022-10-04 10:18:22 +080012728 return RETURN_ERR;
12729 }
12730 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12731
12732 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012733 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012734 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012735 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012736 return RETURN_ERR;
12737 }
12738 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 +080012739
developer74ed4192023-09-21 17:15:17 +080012740 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012741 map->vap_array[i].u.bss_info.enabled = enabled;
12742
developerc086fb72022-10-04 10:18:22 +080012743 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12744 if (ret != RETURN_OK) {
12745 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12746 return RETURN_ERR;
12747 }
developer06a01d92022-09-07 16:32:39 +080012748 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012749
12750 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12751 if (ret != RETURN_OK) {
12752 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12753 return RETURN_ERR;
12754 }
12755 map->vap_array[i].u.bss_info.isolation = enabled;
12756
12757 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12758 if (ret != RETURN_OK) {
12759 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12760 return RETURN_ERR;
12761 }
12762 map->vap_array[i].u.bss_info.bssMaxSta = output;
12763
12764 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12765 if (ret != RETURN_OK) {
12766 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12767 return RETURN_ERR;
12768 }
12769 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012770
developerc086fb72022-10-04 10:18:22 +080012771 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12772 if (ret != RETURN_OK) {
12773 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12774 return RETURN_ERR;
12775 }
12776 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012777
developerc086fb72022-10-04 10:18:22 +080012778 ret = wifi_getApSecurity(vap_index, &security);
12779 if (ret != RETURN_OK) {
12780 printf("%s: wifi_getApSecurity return error\n", __func__);
12781 return RETURN_ERR;
12782 }
12783 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012784
developerc086fb72022-10-04 10:18:22 +080012785 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12786 if (ret != RETURN_OK) {
12787 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12788 return RETURN_ERR;
12789 }
12790 if (mode == 0)
12791 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12792 else
12793 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12794 if (mode == 1)
12795 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12796 else if (mode == 2)
12797 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012798
developerc086fb72022-10-04 10:18:22 +080012799 ret = wifi_getApWmmEnable(vap_index, &enabled);
12800 if (ret != RETURN_OK) {
12801 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12802 return RETURN_ERR;
12803 }
12804 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012805
developerc086fb72022-10-04 10:18:22 +080012806 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12807 if (ret != RETURN_OK) {
12808 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012809 return RETURN_ERR;
12810 }
developerc086fb72022-10-04 10:18:22 +080012811 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012812
12813 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012814 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012815 if (ret != RETURN_OK) {
12816 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12817 return RETURN_ERR;
12818 }
12819 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012820
developerc086fb72022-10-04 10:18:22 +080012821 memset(buf, 0, sizeof(buf));
12822 ret = wifi_getBaseBSSID(vap_index, buf);
12823 if (ret != RETURN_OK) {
12824 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12825 return RETURN_ERR;
12826 }
12827 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12828 &map->vap_array[i].u.bss_info.bssid[0],
12829 &map->vap_array[i].u.bss_info.bssid[1],
12830 &map->vap_array[i].u.bss_info.bssid[2],
12831 &map->vap_array[i].u.bss_info.bssid[3],
12832 &map->vap_array[i].u.bss_info.bssid[4],
12833 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012834 // 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]);
12835
12836 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12837 if (ret != RETURN_OK) {
12838 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12839 return RETURN_ERR;
12840 }
12841 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080012842
12843 ret = wifi_getApWpsEnable(vap_index, &enabled);
12844 if (ret != RETURN_OK) {
12845 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
12846 return RETURN_ERR;
12847 }
12848
12849 map->vap_array[i].u.bss_info.wps.enable = enabled;
12850
developera77d84b2023-02-22 16:10:50 +080012851 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080012852 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012853 }
12854 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12855 return RETURN_OK;
12856}
12857
developer431128d2022-12-16 15:30:41 +080012858
developerd946fd62022-12-08 18:03:28 +080012859static int prepareInterface(UINT apIndex, char *new_interface)
12860{
12861 char cur_interface[16] = {0};
12862 char config_file[128] = {0};
12863 char cmd[128] = {0};
12864 char buf[16] = {0};
12865 int max_radio_num = 0;
12866 int radioIndex = -1;
12867 int phyIndex = -1;
12868
12869 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12870 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12871
12872 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12873 wifi_getMaxRadioNumber(&max_radio_num);
12874 radioIndex = apIndex % max_radio_num;
12875 phyIndex = radio_index_to_phy(radioIndex);
12876 // disable and del old interface, then add new interface
12877 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080012878 if (!(apIndex/max_radio_num)) {
12879 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
12880 _syscmd(cmd, buf, sizeof(buf));
12881 }
developerd946fd62022-12-08 18:03:28 +080012882 }
developer431128d2022-12-16 15:30:41 +080012883 // update the vap status file
12884 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12885 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012886 return RETURN_OK;
12887}
12888
developer06a01d92022-09-07 16:32:39 +080012889INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12890{
developerd946fd62022-12-08 18:03:28 +080012891 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012892 unsigned int i;
12893 wifi_vap_info_t *vap_info = NULL;
12894 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012895 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012896 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012897 char buf[256] = {0};
12898 char cmd[128] = {0};
12899 char config_file[64] = {0};
12900 char bssid[32] = {0};
12901 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012902 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012903
12904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12905 printf("Entering %s index = %d\n", __func__, (int)index);
12906 for (i = 0; i < map->num_vaps; i++)
12907 {
developer1d57d002022-10-12 18:03:15 +080012908 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012909 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012910
12911 // Check vap status file to enable multiple ap if the system boot.
12912 checkVapStatus(vap_info->vap_index, &enable);
12913 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012914 continue;
developer06a01d92022-09-07 16:32:39 +080012915
developer1d57d002022-10-12 18:03:15 +080012916 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12917
developer431128d2022-12-16 15:30:41 +080012918 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12919 enable = FALSE;
12920
12921 // multi-ap first up need to copy current radio config
12922 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012923 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12924 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012925 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12926 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12927 } else {
12928 // Check whether the interface name is valid or this ap change it.
12929 int apIndex = -1;
12930 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12931 if (apIndex != -1 && apIndex != vap_info->vap_index)
12932 continue;
12933 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012934 }
developer06a01d92022-09-07 16:32:39 +080012935
developer1d57d002022-10-12 18:03:15 +080012936 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012937 params[0].name = "interface";
12938 params[0].value = vap_info->vap_name;
12939 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12940 params[1].name = "bssid";
12941 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012942 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012943 params[2].name = "wpa_psk_file";
12944 params[2].value = psk_file;
12945
12946 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12947 wifi_hostapdWrite(config_file, params, 3);
12948
12949 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12950 _syscmd(cmd, buf, sizeof(buf));
12951
12952 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12953 if (ret != RETURN_OK) {
12954 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12955 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012956 }
developer1d57d002022-10-12 18:03:15 +080012957
12958 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12959 if (ret != RETURN_OK) {
12960 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12961 return RETURN_ERR;
12962 }
12963
12964 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12965 if (ret != RETURN_OK) {
12966 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12967 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012968 }
12969
developer1d57d002022-10-12 18:03:15 +080012970 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12971 if (ret != RETURN_OK) {
12972 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12973 return RETURN_ERR;
12974 }
developer06a01d92022-09-07 16:32:39 +080012975
developer1d57d002022-10-12 18:03:15 +080012976 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12977 if (ret != RETURN_OK) {
12978 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12979 return RETURN_ERR;
12980 }
developer06a01d92022-09-07 16:32:39 +080012981
developer1d57d002022-10-12 18:03:15 +080012982 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12983 if (ret != RETURN_OK) {
12984 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12985 return RETURN_ERR;
12986 }
12987
developer804c64f2022-10-19 13:54:40 +080012988 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012989 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012990 }else {
12991 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012992 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012993 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12994 _syscmd(cmd, buf, sizeof(buf));
12995 }else{
developer1d57d002022-10-12 18:03:15 +080012996 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012997 }
developer1d57d002022-10-12 18:03:15 +080012998 }
12999
13000 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13001 if (ret != RETURN_OK) {
13002 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13003 return RETURN_ERR;
13004 }
13005
13006 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13007 if (ret != RETURN_OK) {
13008 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13009 return RETURN_ERR;
13010 }
13011
13012 memset(buf, 0, sizeof(buf));
13013 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13014 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
13015 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13016 if (ret != RETURN_OK) {
13017 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13018 return RETURN_ERR;
13019 }
13020
developer1d57d002022-10-12 18:03:15 +080013021 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13022 if (ret != RETURN_OK) {
13023 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13024 return RETURN_ERR;
13025 }
13026
13027 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13028 if (ret != RETURN_OK) {
13029 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13030 return RETURN_ERR;
13031 }
developer06a01d92022-09-07 16:32:39 +080013032
developer894affa2023-05-10 18:13:19 +080013033 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
13034 if (ret != RETURN_OK) {
13035 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
13036 return RETURN_ERR;
13037 }
13038
developer2f995fb2023-02-24 10:40:44 +080013039 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080013040 if (vap_info->u.bss_info.enabled == TRUE)
13041 wifi_setApEnable(vap_info->vap_index, TRUE);
13042
developer2f995fb2023-02-24 10:40:44 +080013043 multiple_set = FALSE;
13044
13045 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080013046 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080013047 // The set wps methods function should check whether wps is configured.
13048 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
13049 if (ret != RETURN_OK) {
13050 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
13051 return RETURN_ERR;
13052 }
13053 // wifi_setApWpsConfigMethodsEnabled only write to config.
13054 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13055 if (ret != RETURN_OK) {
13056 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13057 return RETURN_ERR;
13058 }
13059 }
developer2f995fb2023-02-24 10:40:44 +080013060
developer894affa2023-05-10 18:13:19 +080013061 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013062 }
developerfb09ba62023-06-09 17:03:21 +080013063
13064 // IGMP Snooping enable should be placed after all hostapd_reload.
13065 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13066 if (ret != RETURN_OK) {
13067 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13068 return RETURN_ERR;
13069 }
13070
developer06a01d92022-09-07 16:32:39 +080013071 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13072 return RETURN_OK;
13073}
13074
13075int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13076{
13077 char *token, *next;
13078 const char s[2] = ",";
13079 int count =0;
13080
13081 /* get the first token */
13082 token = strtok_r(pchannels, s, &next);
13083
13084 /* walk through other tokens */
13085 while( token != NULL && count < MAX_CHANNELS) {
13086 chlistptr->channels_list[count++] = atoi(token);
13087 token = strtok_r(NULL, s, &next);
13088 }
13089
13090 return count;
13091}
13092
13093static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13094{
13095 INT status;
13096 wifi_channels_list_t *chlistp;
13097 CHAR output_string[64];
13098 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013099 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013100 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013101
13102 if(rcap == NULL)
13103 {
13104 return RETURN_ERR;
13105 }
13106
13107 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013108 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013109
developer1e5aa162022-09-13 16:06:24 +080013110 if (band == band_2_4)
13111 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13112 else if (band == band_5)
13113 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13114 else if (band == band_6)
13115 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013116
13117 chlistp = &(rcap->channel_list[0]);
13118 memset(pchannels, 0, sizeof(pchannels));
13119
13120 /* possible number of radio channels */
13121 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13122 {
13123 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13124 }
13125 /* Number of channels and list*/
13126 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13127
13128 /* autoChannelSupported */
13129 /* always ON with wifi_getRadioAutoChannelSupported */
13130 rcap->autoChannelSupported = TRUE;
13131
13132 /* DCSSupported */
13133 /* always ON with wifi_getRadioDCSSupported */
13134 rcap->DCSSupported = TRUE;
13135
13136 /* zeroDFSSupported - TBD */
13137 rcap->zeroDFSSupported = FALSE;
13138
13139 /* Supported Country List*/
13140 memset(output_string, 0, sizeof(output_string));
13141 status = wifi_getRadioCountryCode(radioIndex, output_string);
13142 if( status != 0 ) {
13143 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13144 return RETURN_ERR;
13145 } else {
13146 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13147 }
13148 if(!strcmp(output_string,"US")){
13149 rcap->countrySupported[0] = wifi_countrycode_US;
13150 rcap->countrySupported[1] = wifi_countrycode_CA;
13151 } else if (!strcmp(output_string,"CA")) {
13152 rcap->countrySupported[0] = wifi_countrycode_CA;
13153 rcap->countrySupported[1] = wifi_countrycode_US;
13154 } else {
13155 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13156 }
13157
13158 rcap->numcountrySupported = 2;
13159
13160 /* csi */
13161 rcap->csi.maxDevices = 8;
13162 rcap->csi.soudingFrameSupported = TRUE;
13163
developer7930d352022-12-21 17:55:42 +080013164 wifi_GetInterfaceName(radioIndex, interface_name);
13165 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013166
13167 /* channelWidth - all supported bandwidths */
13168 int i=0;
13169 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013170
13171 /* mode - all supported variants */
13172 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13173 wifi_getRadioSupportedStandards(radioIndex, output_string);
13174
developer06a01d92022-09-07 16:32:39 +080013175 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13176 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13177 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013178 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013179
developer7c4cd202023-03-01 10:56:29 +080013180 if (strstr(output_string, "n") != NULL)
13181 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13182 if (strstr(output_string, "ax") != NULL)
13183 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13184 if (strstr(output_string, "be") != NULL)
13185 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13186 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013187 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13188 WIFI_CHANNELBANDWIDTH_40MHZ |
13189 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013190 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013191
developer7c4cd202023-03-01 10:56:29 +080013192 if (strstr(output_string, "n") != NULL)
13193 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13194 if (strstr(output_string, "ac") != NULL)
13195 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13196 if (strstr(output_string, "ax") != NULL)
13197 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13198 if (strstr(output_string, "be") != NULL)
13199 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13200 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13201 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13202 WIFI_CHANNELBANDWIDTH_40MHZ |
13203 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013204 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013205
13206 if (strstr(output_string, "be") != NULL) {
13207 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13208 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13209 }
developer06a01d92022-09-07 16:32:39 +080013210 }
developer7c4cd202023-03-01 10:56:29 +080013211
developer06a01d92022-09-07 16:32:39 +080013212 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13213 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13214
13215 /* supportedBitRate - all supported bitrates */
13216 rcap->supportedBitRate[i] = 0;
13217 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13218 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13219 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13220 }
developer1e5aa162022-09-13 16:06:24 +080013221 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013222 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13223 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13224 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13225 }
13226
13227
13228 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13229 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13230 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13231 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13232 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13233 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13234 rcap->cipherSupported = 0;
13235 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13236 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13237
13238 return RETURN_OK;
13239}
13240
13241INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13242{
developer30423732022-12-01 16:17:49 +080013243 INT status = 0, radioIndex = 0;
13244 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013245 int iter = 0;
developer30423732022-12-01 16:17:49 +080013246 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013247 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013248 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013249
13250 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13251
13252 memset(cap, 0, sizeof(wifi_hal_capability_t));
13253
13254 /* version */
13255 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13256 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13257
13258 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013259 wifi_getMaxRadioNumber(&max_num_radios);
13260 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013261
13262 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13263 {
13264 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13265 if (status != 0) {
13266 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13267 return RETURN_ERR;
13268 }
13269
13270 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13271 {
developer804c64f2022-10-19 13:54:40 +080013272 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013273 {
13274 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13275 return RETURN_ERR;
13276 }
13277 iface_info = &cap->wifi_prop.interface_map[iter];
13278 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13279 iface_info->rdk_radio_index = radioIndex;
13280 memset(output, 0, sizeof(output));
13281 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13282 {
13283 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13284 }
13285 // TODO: bridge name
13286 // TODO: vlan id
13287 // TODO: primary
13288 iface_info->index = array_index_to_vap_index(radioIndex, j);
13289 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013290 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013291 {
13292 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13293 }
13294 iter++;
13295 }
13296 }
13297
13298 cap->BandSteeringSupported = FALSE;
13299 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13300 return RETURN_OK;
13301}
13302
developer9df4e652022-10-11 11:27:38 +080013303INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13304{
13305 struct params h_config={0};
13306 char config_file[64] = {0};
13307
13308 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13309
13310 h_config.name = "okc";
13311 h_config.value = okc_enable?"1":"0";
13312
13313 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13314 wifi_hostapdWrite(config_file, &h_config, 1);
13315 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13316
13317 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13318 return RETURN_OK;
13319}
13320
13321INT wifi_setSAEMFP(int ap_index, BOOL enable)
13322{
13323 struct params h_config={0};
13324 char config_file[64] = {0};
13325 char buf[128] = {0};
13326
13327 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13328
13329 h_config.name = "sae_require_mfp";
13330 h_config.value = enable?"1":"0";
13331
13332 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13333 wifi_hostapdWrite(config_file, &h_config, 1);
13334 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13335
13336 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13337 return RETURN_OK;
13338}
13339
13340INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13341{
13342 struct params h_config={0};
13343 char config_file[64] = {0};
13344 char buf[128] = {0};
13345
13346 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13347
13348 h_config.name = "sae_pwe";
13349 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13350 h_config.value = buf;
13351
13352 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13353 wifi_hostapdWrite(config_file, &h_config, 1);
13354 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13355
13356 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13357 return RETURN_OK;
13358}
13359
13360INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13361{
13362 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13363 struct params h_config={0};
13364 char config_file[64] = {0};
13365
13366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13367
13368 h_config.name = "wpa_disable_eapol_key_retries";
13369 h_config.value = disable_EAPOL_retries?"1":"0";
13370
13371 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13372 wifi_hostapdWrite(config_file, &h_config, 1);
13373 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13374
13375 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13376 return RETURN_OK;
13377}
13378
developer06a01d92022-09-07 16:32:39 +080013379INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13380{
developer587c1b62022-09-27 15:58:59 +080013381 char buf[128] = {0};
13382 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013383 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013384 char password[64] = {0};
13385 char mfp[32] = {0};
13386 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013387 BOOL okc_enable = FALSE;
13388 BOOL sae_MFP = FALSE;
13389 BOOL disable_EAPOL_retries = TRUE;
13390 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013391 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013392 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013393
13394 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13395
13396 multiple_set = TRUE;
13397 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13398 if (security->mode == wifi_security_mode_none) {
13399 strcpy(wpa_mode, "None");
13400 } else if (security->mode == wifi_security_mode_wpa_personal)
13401 strcpy(wpa_mode, "WPA-Personal");
13402 else if (security->mode == wifi_security_mode_wpa2_personal)
13403 strcpy(wpa_mode, "WPA2-Personal");
13404 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13405 strcpy(wpa_mode, "WPA-WPA2-Personal");
13406 else if (security->mode == wifi_security_mode_wpa_enterprise)
13407 strcpy(wpa_mode, "WPA-Enterprise");
13408 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13409 strcpy(wpa_mode, "WPA2-Enterprise");
13410 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13411 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013412 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013413 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013414 okc_enable = TRUE;
13415 sae_MFP = TRUE;
13416 sae_pwe = 2;
13417 disable_EAPOL_retries = FALSE;
13418 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013419 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013420 okc_enable = TRUE;
13421 sae_MFP = TRUE;
13422 sae_pwe = 2;
13423 disable_EAPOL_retries = FALSE;
13424 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013425 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013426 sae_MFP = TRUE;
13427 sae_pwe = 2;
13428 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013429 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013430 strcpy(wpa_mode, "OWE");
13431 sae_MFP = TRUE;
13432 sae_pwe = 2;
13433 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013434 }
13435
13436 band = wifi_index_to_band(ap_index);
13437 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13438 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13439 return RETURN_ERR;
13440 }
developer587c1b62022-09-27 15:58:59 +080013441
13442 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013443 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013444 wifi_setSAEMFP(ap_index, sae_MFP);
13445 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013446 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013447
developerae432c62023-04-24 11:07:20 +080013448 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013449 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) {
13450 int key_len = strlen(security->u.key.key);
13451 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13452 if (key_len == 64) { // set wpa_psk
13453 strncpy(password, security->u.key.key, 64); // 64 characters
13454 password[64] = '\0';
13455 wifi_setApSecurityPreSharedKey(ap_index, password);
13456 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13457 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13458 strncpy(password, security->u.key.key, 63);
13459 password[63] = '\0';
13460 wifi_setApSecurityKeyPassphrase(ap_index, password);
13461 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13462 } else
13463 return RETURN_ERR;
13464 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013465 }
13466 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13467 params.name = "sae_password";
13468 params.value = security->u.key.key;
13469 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013470 } else { // remove sae_password
13471 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13472 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013473 }
13474 }
developer587c1b62022-09-27 15:58:59 +080013475
13476 if (security->mode != wifi_security_mode_none) {
13477 memset(&params, 0, sizeof(params));
13478 params.name = "wpa_pairwise";
13479 if (security->encr == wifi_encryption_tkip)
13480 params.value = "TKIP";
13481 else if (security->encr == wifi_encryption_aes)
13482 params.value = "CCMP";
13483 else if (security->encr == wifi_encryption_aes_tkip)
13484 params.value = "TKIP CCMP";
13485 wifi_hostapdWrite(config_file, &params, 1);
13486 }
13487
13488 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013489 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013490 else if (security->mfp == wifi_mfp_cfg_optional)
13491 strcpy(mfp, "Optional");
13492 else if (security->mfp == wifi_mfp_cfg_required)
13493 strcpy(mfp, "Required");
13494 wifi_setApSecurityMFPConfig(ap_index, mfp);
13495
13496 memset(&params, 0, sizeof(params));
13497 params.name = "transition_disable";
13498 if (security->wpa3_transition_disable == TRUE)
13499 params.value = "0x01";
13500 else
13501 params.value = "0x00";
13502 wifi_hostapdWrite(config_file, &params, 1);
13503
13504 memset(&params, 0, sizeof(params));
13505 params.name = "wpa_group_rekey";
13506 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13507 params.value = buf;
13508 wifi_hostapdWrite(config_file, &params, 1);
13509
13510 memset(&params, 0, sizeof(params));
13511 params.name = "wpa_strict_rekey";
13512 params.value = security->strict_rekey?"1":"0";
13513 wifi_hostapdWrite(config_file, &params, 1);
13514
13515 memset(&params, 0, sizeof(params));
13516 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013517 if (security->eapol_key_retries == 0)
13518 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013519 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13520 params.value = buf;
13521 wifi_hostapdWrite(config_file, &params, 1);
13522
13523 memset(&params, 0, sizeof(params));
13524 params.name = "disable_pmksa_caching";
13525 params.value = security->disable_pmksa_caching?"1":"0";
13526 wifi_hostapdWrite(config_file, &params, 1);
13527
developer23e71282023-01-18 10:25:19 +080013528 if (multiple_set == FALSE) {
13529 wifi_setApEnable(ap_index, FALSE);
13530 wifi_setApEnable(ap_index, TRUE);
13531 }
developer587c1b62022-09-27 15:58:59 +080013532
13533 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13534
developer06a01d92022-09-07 16:32:39 +080013535 return RETURN_OK;
13536}
13537
13538INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13539{
developer9df4e652022-10-11 11:27:38 +080013540 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013541 char config_file[128] = {0};
13542 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013543 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013544
13545 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13546 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13547 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13548 security->mode = wifi_security_mode_none;
13549 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013550 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013551 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013552 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013553 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013554 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013555 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013556 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013557 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013558 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013559 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013560 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013561 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013562 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013563 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013564 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013565 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013566 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013567 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013568 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013569 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013570 }
13571
13572 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13573 if (security->mode == wifi_security_mode_none)
13574 security->encr = wifi_encryption_none;
13575 else {
13576 if (strcmp(buf, "TKIP") == 0)
13577 security->encr = wifi_encryption_tkip;
13578 else if (strcmp(buf, "CCMP") == 0)
13579 security->encr = wifi_encryption_aes;
13580 else
13581 security->encr = wifi_encryption_aes_tkip;
13582 }
13583
developer9df4e652022-10-11 11:27:38 +080013584 if (security->mode != wifi_encryption_none) {
13585 memset(buf, 0, sizeof(buf));
13586 // wpa3 can use one or both configs as password, so we check sae_password first.
13587 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013588 if (strlen(buf) != 0) {
13589 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13590 security->u.key.type = wifi_security_key_type_sae;
13591 set_sae = TRUE;
13592 strncpy(security->u.key.key, buf, sizeof(buf));
13593 }
13594 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13595 if (strlen(buf) != 0){
13596 if (set_sae == TRUE)
13597 security->u.key.type = wifi_security_key_type_psk_sae;
13598 else if (strlen(buf) == 64)
13599 security->u.key.type = wifi_security_key_type_psk;
13600 else
13601 security->u.key.type = wifi_security_key_type_pass;
13602 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013603 }
developer9df4e652022-10-11 11:27:38 +080013604 security->u.key.key[255] = '\0';
13605 }
13606
developer587c1b62022-09-27 15:58:59 +080013607 memset(buf, 0, sizeof(buf));
13608 wifi_getApSecurityMFPConfig(ap_index, buf);
13609 if (strcmp(buf, "Disabled") == 0)
13610 security->mfp = wifi_mfp_cfg_disabled;
13611 else if (strcmp(buf, "Optional") == 0)
13612 security->mfp = wifi_mfp_cfg_optional;
13613 else if (strcmp(buf, "Required") == 0)
13614 security->mfp = wifi_mfp_cfg_required;
13615
13616 memset(buf, 0, sizeof(buf));
13617 security->wpa3_transition_disable = FALSE;
13618 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13619 disable = strtol(buf, NULL, 16);
13620 if (disable != 0)
13621 security->wpa3_transition_disable = TRUE;
13622
13623 memset(buf, 0, sizeof(buf));
13624 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13625 if (strlen(buf) == 0)
13626 security->rekey_interval = 86400;
13627 else
13628 security->rekey_interval = strtol(buf, NULL, 10);
13629
13630 memset(buf, 0, sizeof(buf));
13631 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13632 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013633 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013634 else
13635 security->strict_rekey = strtol(buf, NULL, 10);
13636
13637 memset(buf, 0, sizeof(buf));
13638 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13639 if (strlen(buf) == 0)
13640 security->eapol_key_retries = 4;
13641 else
13642 security->eapol_key_retries = strtol(buf, NULL, 10);
13643
13644 memset(buf, 0, sizeof(buf));
13645 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13646 if (strlen(buf) == 0)
13647 security->disable_pmksa_caching = FALSE;
13648 else
13649 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13650
13651 /* TODO
13652 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13653 */
13654 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13655 security->eap_identity_req_timeout = 0;
13656 security->eap_identity_req_retries = 0;
13657 security->eap_req_timeout = 0;
13658 security->eap_req_retries = 0;
13659 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013660 return RETURN_OK;
13661}
13662
13663#endif /* WIFI_HAL_VERSION_3 */
13664
13665#ifdef WIFI_HAL_VERSION_3_PHASE2
13666INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13667{
developerd946fd62022-12-08 18:03:28 +080013668 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013669 char cmd[128] = {0};
13670 char buf[128] = {0};
13671 char *mac_addr = NULL;
13672 BOOL status = FALSE;
13673 size_t len = 0;
13674
13675 if(ap_index > MAX_APS)
13676 return RETURN_ERR;
13677
13678 *output_numDevices = 0;
13679 wifi_getApEnable(ap_index, &status);
13680 if (status == FALSE)
13681 return RETURN_OK;
13682
developerac6f1142022-12-20 19:26:35 +080013683 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013684 return RETURN_ERR;
13685 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013686 _syscmd(cmd, buf, sizeof(buf));
13687
13688 mac_addr = strtok(buf, "\n");
13689 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13690 *output_numDevices = i + 1;
13691 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13692 addr_ptr = output_deviceMacAddressArray[i];
13693 mac_addr_aton(addr_ptr, mac_addr);
13694 mac_addr = strtok(NULL, "\n");
13695 }
13696
13697 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013698}
13699#else
13700INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13701{
developerd946fd62022-12-08 18:03:28 +080013702 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013703 char cmd[128];
13704 BOOL status = false;
13705
13706 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13707 return RETURN_ERR;
13708
13709 output_buf[0] = '\0';
13710
13711 wifi_getApEnable(ap_index,&status);
13712 if (!status)
13713 return RETURN_OK;
13714
developerac6f1142022-12-20 19:26:35 +080013715 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013716 return RETURN_ERR;
13717 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013718 _syscmd(cmd, output_buf, output_buf_size);
13719
13720 return RETURN_OK;
13721}
13722#endif
developer2f513ab2022-09-13 14:26:06 +080013723
13724INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13725{
13726 char output[16]={'\0'};
13727 char config_file[MAX_BUF_SIZE] = {0};
13728
13729 if (!enable)
13730 return RETURN_ERR;
13731
13732 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13733 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13734
13735 if (strlen(output) == 0)
13736 *enable = FALSE;
13737 else if (strncmp(output, "1", 1) == 0)
13738 *enable = TRUE;
13739 else
13740 *enable = FALSE;
13741
13742 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13743 return RETURN_OK;
13744}
developer2d9c30f2022-09-13 15:06:14 +080013745
13746INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13747{
developer804c64f2022-10-19 13:54:40 +080013748 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013749 return RETURN_ERR;
13750 *output_enable=TRUE;
13751 return RETURN_OK;
13752}
developerfd7d2892022-09-13 16:44:53 +080013753
13754INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13755{
13756 char cmd[128] = {0};
13757 char buf[128] = {0};
13758 char line[128] = {0};
13759 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013760 FILE *f = NULL;
13761 int index = 0;
13762 int exp = 0;
13763 int mantissa = 0;
13764 int duration = 0;
13765 int radio_index = 0;
13766 int max_radio_num = 0;
13767 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013768 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013769 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13770
13771 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013772
developerfd7d2892022-09-13 16:44:53 +080013773 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013774
13775 phyId = radio_index_to_phy(radio_index);
13776 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013777 _syscmd(cmd, buf, sizeof(buf));
13778 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13779 if (*numSessionReturned > maxNumberSessions)
13780 *numSessionReturned = maxNumberSessions;
13781 else if (*numSessionReturned < 1) {
13782 *numSessionReturned = 0;
13783 return RETURN_OK;
13784 }
13785
developer033b37b2022-10-18 11:27:46 +080013786 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 +080013787 if ((f = popen(cmd, "r")) == NULL) {
13788 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13789 return RETURN_ERR;
13790 }
13791
13792 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013793 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013794 char *tmp = NULL;
13795 strcpy(buf, line);
13796 tmp = strtok(buf, " ");
13797 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13798 tmp = strtok(NULL, " ");
13799 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13800 tmp = strtok(NULL, " ");
13801 if (strstr(tmp, "t")) {
13802 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13803 }
13804 if (strstr(tmp, "a")) {
13805 twtSessions[index].twtParameters.operation.announced = TRUE;
13806 }
13807 tmp = strtok(NULL, " ");
13808 exp = strtol(tmp, NULL, 10);
13809 tmp = strtok(NULL, " ");
13810 mantissa = strtol(tmp, NULL, 10);
13811 tmp = strtok(NULL, " ");
13812 duration = strtol(tmp, NULL, 10);
13813
13814 // only implicit supported
13815 twtSessions[index].twtParameters.operation.implicit = TRUE;
13816 // only individual agreement supported
13817 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13818
13819 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13820 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013821 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013822 // Overflow handling
13823 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13824 } else {
13825 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13826 }
13827 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13828 index++;
13829 }
13830
13831 pclose(f);
13832 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13833 return RETURN_OK;
13834}