blob: 28f98b4130808298398250cfc61f2129bc9f6b51 [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__);
developer214b0592023-10-31 10:59:05 +08003570 CHAR buf[MAX_CMD_SIZE] = {0};
3571 CHAR Value[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08003572 FILE *fp = NULL;
3573
3574 if (ifname == NULL || strlen(ifname) <= 1)
3575 return RETURN_OK;
3576
developer214b0592023-10-31 10:59:05 +08003577 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
developer06a01d92022-09-07 16:32:39 +08003578 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
developer214b0592023-10-31 10:59:05 +08003588 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);
developer06a01d92022-09-07 16:32:39 +08003591
developer214b0592023-10-31 10:59:05 +08003592 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);
developer06a01d92022-09-07 16:32:39 +08003595
developer214b0592023-10-31 10:59:05 +08003596 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);
developer06a01d92022-09-07 16:32:39 +08003599
developer214b0592023-10-31 10:59:05 +08003600 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);
developer06a01d92022-09-07 16:32:39 +08003603
developer214b0592023-10-31 10:59:05 +08003604 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);
developer06a01d92022-09-07 16:32:39 +08003607
developer214b0592023-10-31 10:59:05 +08003608 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);
developer06a01d92022-09-07 16:32:39 +08003611
developer214b0592023-10-31 10:59:05 +08003612 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);
developer06a01d92022-09-07 16:32:39 +08003615
developer214b0592023-10-31 10:59:05 +08003616 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);
developer06a01d92022-09-07 16:32:39 +08003619
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};
developer7c4c40e2023-10-25 10:17:04 +08003677 INT max_radio_num = 0, apIndex = 0;
developer06a01d92022-09-07 16:32:39 +08003678
3679 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3680 if (NULL == output_struct)
3681 return RETURN_ERR;
3682
developer7c4c40e2023-10-25 10:17:04 +08003683 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08003684
developer7c4c40e2023-10-25 10:17:04 +08003685 memset(output_struct, 0, sizeof(wifi_radioTrafficStats2_t));
developer06a01d92022-09-07 16:32:39 +08003686
developer7c4c40e2023-10-25 10:17:04 +08003687 for(apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
3688 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3689 continue;
3690 wifi_getApEnable(radioIndex, &iface_status);
3691
3692 if (iface_status == TRUE)
3693 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3694 else
3695 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003696
developer7c4c40e2023-10-25 10:17:04 +08003697 output_struct->radio_BytesSent += radioTrafficStats.radio_BytesSent;
3698 output_struct->radio_BytesReceived += radioTrafficStats.radio_BytesReceived;
3699 output_struct->radio_PacketsSent += radioTrafficStats.radio_PacketsSent;
3700 output_struct->radio_PacketsReceived += radioTrafficStats.radio_PacketsReceived;
3701 output_struct->radio_ErrorsSent += radioTrafficStats.radio_ErrorsSent;
3702 output_struct->radio_ErrorsReceived += radioTrafficStats.radio_ErrorsReceived;
3703 output_struct->radio_DiscardPacketsSent += radioTrafficStats.radio_DiscardPacketsSent;
3704 output_struct->radio_DiscardPacketsReceived += radioTrafficStats.radio_DiscardPacketsReceived;
3705 }
developer06a01d92022-09-07 16:32:39 +08003706
3707 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3708 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].
3709 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3710 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.
3711 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
3712 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
3713 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
3714 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
3715 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
3716
3717 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
3718 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
3719 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
3720 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.
3721
3722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3723
3724 return RETURN_OK;
3725}
3726
3727//Set radio traffic static Measureing rules
3728INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3729{
3730 //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
3731 // Else, save the MeasuringRate and MeasuringInterval for future usage
3732
3733 return RETURN_OK;
3734}
3735
3736//To start or stop RadioTrafficStats
3737INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3738{
3739 //zqiu: If the RadioTrafficStats process running
3740 // if(enable)
3741 // return RETURN_OK.
3742 // else
3743 // Stop RadioTrafficStats process
3744 // Else
3745 // if(enable)
3746 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3747 // else
3748 // return RETURN_OK.
3749
3750 return RETURN_OK;
3751}
3752
3753//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
3754INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3755{
3756 //zqiu: Please ignor signalIndex.
3757 if (NULL == SignalLevel)
3758 return RETURN_ERR;
3759 *SignalLevel=(radioIndex==0)?-19:-19;
3760
3761 return RETURN_OK;
3762}
3763
3764//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3765INT wifi_applyRadioSettings(INT radioIndex)
3766{
3767 return RETURN_OK;
3768}
3769
3770//Get the radio index assocated with this SSID entry
3771INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3772{
developer5b398df2022-11-17 20:39:48 +08003773 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003774 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003775 int max_radio_num = 0;
3776 wifi_getMaxRadioNumber(&max_radio_num);
3777 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003778 return RETURN_OK;
3779}
3780
3781//Device.WiFi.SSID.{i}.Enable
3782//Get SSID enable configuration parameters (not the SSID enable status)
3783INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3784{
3785 if (NULL == output_bool)
3786 return RETURN_ERR;
3787
developer06a01d92022-09-07 16:32:39 +08003788 return wifi_getApEnable(ssidIndex, output_bool);
3789}
3790
3791//Device.WiFi.SSID.{i}.Enable
3792//Set SSID enable configuration parameters
3793INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3794{
developer06a01d92022-09-07 16:32:39 +08003795 return wifi_setApEnable(ssidIndex, enable);
3796}
3797
3798//Device.WiFi.SSID.{i}.Status
3799//Get the SSID enable status
3800INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3801{
3802 char cmd[MAX_CMD_SIZE]={0};
3803 char buf[MAX_BUF_SIZE]={0};
3804 BOOL output_bool;
3805
3806 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3807 if (NULL == output_string)
3808 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003809
developer06a01d92022-09-07 16:32:39 +08003810 wifi_getApEnable(ssidIndex,&output_bool);
3811 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3812
3813 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3814 return RETURN_OK;
3815}
3816
3817// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3818INT wifi_getSSIDName(INT apIndex, CHAR *output)
3819{
3820 char config_file[MAX_BUF_SIZE] = {0};
3821
3822 if (NULL == output)
3823 return RETURN_ERR;
3824
3825 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3826 wifi_hostapdRead(config_file,"ssid",output,32);
3827
3828 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3829 return RETURN_OK;
3830}
3831
3832// Set a max 32 byte string and sets an internal variable to the SSID name
3833INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3834{
3835 char str[MAX_BUF_SIZE]={'\0'};
3836 char cmd[MAX_CMD_SIZE]={'\0'};
3837 struct params params;
3838 char config_file[MAX_BUF_SIZE] = {0};
3839
3840 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003841 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003842 return RETURN_ERR;
3843
3844 params.name = "ssid";
3845 params.value = ssid_string;
3846 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3847 wifi_hostapdWrite(config_file, &params, 1);
3848 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3850
3851 return RETURN_OK;
3852}
3853
3854//Get the BSSID
3855INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3856{
3857 char cmd[MAX_CMD_SIZE]="";
3858
3859 if (NULL == output_string)
3860 return RETURN_ERR;
3861
3862 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3863 {
developer1d57d002022-10-12 18:03:15 +08003864 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 +08003865 _syscmd(cmd, output_string, 64);
3866 return RETURN_OK;
3867 }
3868 strncpy(output_string, "\0", 1);
3869
3870 return RETURN_ERR;
3871}
3872
3873//Get the MAC address associated with this Wifi SSID
3874INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3875{
3876 wifi_getBaseBSSID(ssidIndex,output_string);
3877 return RETURN_OK;
3878}
3879
3880//Get the basic SSID traffic static info
3881//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3882//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3883INT wifi_applySSIDSettings(INT ssidIndex)
3884{
developerd946fd62022-12-08 18:03:28 +08003885 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003886 BOOL status = false;
3887 char cmd[MAX_CMD_SIZE] = {0};
3888 char buf[MAX_CMD_SIZE] = {0};
3889 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003890 int max_radio_num = 0;
3891 int radioIndex = 0;
3892
3893 wifi_getMaxRadioNumber(&max_radio_num);
3894
3895 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003896
3897 wifi_getApEnable(ssidIndex,&status);
3898 // Do not apply when ssid index is disabled
3899 if (status == false)
3900 return RETURN_OK;
3901
3902 /* Doing full remove and add for ssid Index
3903 * Not all hostapd options are supported with reload
3904 * for example macaddr_acl
3905 */
3906 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3907 return RETURN_ERR;
3908
3909 ret = wifi_setApEnable(ssidIndex,true);
3910
3911 /* Workaround for hostapd issue with multiple bss definitions
3912 * when first created interface will be removed
3913 * then all vaps other vaps on same phy are removed
3914 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003915 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003916 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003917 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003918 continue;
developer643b28f2023-04-04 10:26:01 +08003919 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003920 _syscmd(cmd, buf, sizeof(buf));
3921 if(*buf == '1')
3922 wifi_setApEnable(apIndex, true);
3923 }
3924
3925 return ret;
3926}
3927
developera3c68b92022-09-13 15:27:29 +08003928struct channels_noise {
3929 int channel;
3930 int noise;
3931};
3932
3933// Return noise array for each channel
3934int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3935{
developerd946fd62022-12-08 18:03:28 +08003936 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003937 FILE *f = NULL;
3938 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003939 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003940 size_t len = 0;
3941 ssize_t read = 0;
3942 int tmp = 0, arr_index = -1;
3943
developerac6f1142022-12-20 19:26:35 +08003944 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003945 return RETURN_ERR;
3946 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003947
3948 if ((f = popen(cmd, "r")) == NULL) {
3949 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3950 return RETURN_ERR;
3951 }
developer5550e242022-09-30 09:59:32 +08003952
3953 while(fgets(line, sizeof(line), f) != NULL) {
3954 if(arr_index < channels_num){
3955 sscanf(line, "%d", &tmp);
3956 if (tmp > 0) { // channel frequency, the first line must be frequency
3957 arr_index++;
3958 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3959 } else { // noise
3960 channels_noise_arr[arr_index].noise = tmp;
3961 }
3962 }else{
3963 break;
developera3c68b92022-09-13 15:27:29 +08003964 }
3965 }
developera3c68b92022-09-13 15:27:29 +08003966 pclose(f);
3967 return RETURN_OK;
3968}
3969
developer06a01d92022-09-07 16:32:39 +08003970//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3971//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3972INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3973{
developera3c68b92022-09-13 15:27:29 +08003974 int index = -1;
3975 wifi_neighbor_ap2_t *scan_array = NULL;
3976 char cmd[256]={0};
3977 char buf[128]={0};
3978 char file_name[32] = {0};
3979 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003980 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003981 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003982 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003983 int freq=0;
3984 FILE *f = NULL;
3985 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003986 int channels_num = 0;
3987 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003988 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003989 bool filter_enable = false;
3990 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003991 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003992
developer615510b2022-09-27 10:14:35 +08003993 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003994
developerac6f1142022-12-20 19:26:35 +08003995 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003996 return RETURN_ERR;
3997
developera3c68b92022-09-13 15:27:29 +08003998 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3999 f = fopen(file_name, "r");
4000 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08004001 fgets(buf, sizeof(file_name), f);
4002 if ((strncmp(buf, "0", 1)) != 0) {
4003 fgets(filter_SSID, sizeof(file_name), f);
4004 if (strlen(filter_SSID) != 0)
4005 filter_enable = true;
4006 }
developera3c68b92022-09-13 15:27:29 +08004007 fclose(f);
4008 }
4009
developer033b37b2022-10-18 11:27:46 +08004010 phyId = radio_index_to_phy(radioIndex);
4011 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08004012 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08004013 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004014
developer5550e242022-09-30 09:59:32 +08004015
developer06a01d92022-09-07 16:32:39 +08004016
developerd946fd62022-12-08 18:03:28 +08004017 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4018 // 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 +08004019 fprintf(stderr, "cmd: %s\n", cmd);
4020 if ((f = popen(cmd, "r")) == NULL) {
4021 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4022 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004023 }
developer5550e242022-09-30 09:59:32 +08004024
4025 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4026 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
4027
developer615510b2022-09-27 10:14:35 +08004028 ret = fgets(line, sizeof(line), f);
4029 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08004030 if(strstr(line, "BSS") != NULL) { // new neighbor info
4031 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
4032 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4033 // 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 +08004034
developera3c68b92022-09-13 15:27:29 +08004035 if (!filter_BSS) {
4036 index++;
4037 wifi_neighbor_ap2_t *tmp;
4038 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4039 if (tmp == NULL) { // no more memory to use
4040 index--;
4041 wifi_dbg_printf("%s: realloc failed\n", __func__);
4042 break;
4043 }
4044 scan_array = tmp;
4045 }
4046 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4047
4048 filter_BSS = false;
4049 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4050 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4051 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4052 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4053 } else if (strstr(line, "freq") != NULL) {
4054 sscanf(line," freq: %d", &freq);
4055 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4056
4057 if (freq >= 2412 && freq <= 2484) {
4058 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4059 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4060 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4061 }
4062 else if (freq >= 5160 && freq <= 5805) {
4063 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4064 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4065 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4066 }
4067
4068 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08004069 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08004070 for (int i = 0; i < channels_num; i++) {
4071 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4072 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4073 break;
4074 }
4075 }
4076 }
4077 } else if (strstr(line, "beacon interval") != NULL) {
4078 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4079 } else if (strstr(line, "signal") != NULL) {
4080 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4081 } else if (strstr(line,"SSID") != NULL) {
4082 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4083 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4084 filter_BSS = true;
4085 }
4086 } else if (strstr(line, "Supported rates") != NULL) {
4087 char SRate[80] = {0}, *tmp = NULL;
4088 memset(buf, 0, sizeof(buf));
4089 strcpy(SRate, line);
4090 tmp = strtok(SRate, ":");
4091 tmp = strtok(NULL, ":");
4092 strcpy(buf, tmp);
4093 memset(SRate, 0, sizeof(SRate));
4094
4095 tmp = strtok(buf, " \n");
4096 while (tmp != NULL) {
4097 strcat(SRate, tmp);
4098 if (SRate[strlen(SRate) - 1] == '*') {
4099 SRate[strlen(SRate) - 1] = '\0';
4100 }
4101 strcat(SRate, ",");
4102
4103 tmp = strtok(NULL, " \n");
4104 }
4105 SRate[strlen(SRate) - 1] = '\0';
4106 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4107 } else if (strstr(line, "DTIM") != NULL) {
4108 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4109 } else if (strstr(line, "VHT capabilities") != NULL) {
4110 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4111 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4112 } else if (strstr(line, "HT capabilities") != NULL) {
4113 strcat(scan_array[index].ap_SupportedStandards, ",n");
4114 strcpy(scan_array[index].ap_OperatingStandards, "n");
4115 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004116 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004117 sscanf(line," * channel width: %d", &vht_channel_width);
4118 if(vht_channel_width == 1) {
4119 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4120 } else {
4121 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4122 }
4123 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4124 continue;
4125 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004126 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004127 sscanf(line," * secondary channel offset: %s", &buf);
4128 if (!strcmp(buf, "above")) {
4129 //40Mhz +
4130 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4131 }
4132 else if (!strcmp(buf, "below")) {
4133 //40Mhz -
4134 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4135 } else {
4136 //20Mhz
4137 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4138 }
4139 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4140 continue;
4141 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004142 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4143 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4144 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004145 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4146 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004147 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004148 else
developer615510b2022-09-27 10:14:35 +08004149 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004150 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004151 if (strstr(line, "HE80/5GHz") != NULL) {
4152 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4153 ret = fgets(line, sizeof(line), f);
4154 } else
4155 continue;
developera3c68b92022-09-13 15:27:29 +08004156 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004157 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004158 }
developer615510b2022-09-27 10:14:35 +08004159 continue;
developera3c68b92022-09-13 15:27:29 +08004160 } else if (strstr(line, "WPA") != NULL) {
4161 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4162 } else if (strstr(line, "RSN") != NULL) {
4163 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4164 } else if (strstr(line, "Group cipher") != NULL) {
4165 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4166 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4167 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4168 }
4169 }
developer615510b2022-09-27 10:14:35 +08004170 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004171 }
4172
4173 if (!filter_BSS) {
4174 *output_array_size = index + 1;
4175 } else {
4176 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4177 *output_array_size = index;
4178 }
4179 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004180 pclose(f);
developer5550e242022-09-30 09:59:32 +08004181 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004182 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004183 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004184}
4185
4186//>> Deprecated: used for old RDKB code.
4187INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4188{
4189 INT status = RETURN_ERR;
4190
4191 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4192 output_struct->wifi_PLCPErrorCount = 0;
4193 output_struct->wifi_FCSErrorCount = 0;
4194 output_struct->wifi_InvalidMACCount = 0;
4195 output_struct->wifi_PacketsOtherReceived = 0;
4196 output_struct->wifi_Noise = 0;
4197 status = RETURN_OK;
4198 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4199 return status;
4200}
4201
4202INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4203{
developerd946fd62022-12-08 18:03:28 +08004204 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004205 char cmd[128] = {0};
4206 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004207 char *pos = NULL;
4208
4209 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4210 if (NULL == output_struct)
4211 return RETURN_ERR;
4212
developerac6f1142022-12-20 19:26:35 +08004213 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004214 return RETURN_ERR;
4215
developer06a01d92022-09-07 16:32:39 +08004216 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4217
developerd946fd62022-12-08 18:03:28 +08004218 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004219 _syscmd(cmd, buf, sizeof(buf));
4220
4221 pos = buf;
4222 if ((pos = strstr(pos, "RX packets:")) == NULL)
4223 return RETURN_ERR;
4224 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4225
4226 if ((pos = strstr(pos, "TX packets:")) == NULL)
4227 return RETURN_ERR;
4228 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4229
4230 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4231 return RETURN_ERR;
4232 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4233
4234 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4235 return RETURN_ERR;
4236 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4237
developerd946fd62022-12-08 18:03:28 +08004238 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004239 _syscmd(cmd, buf, sizeof(buf));
4240 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4241
4242#if 0
4243 //TODO: need to revisit below implementation
4244 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4245 char interface_name[MAX_BUF_SIZE] = {0};
4246 char interface_status[MAX_BUF_SIZE] = {0};
4247 char Value[MAX_BUF_SIZE] = {0};
4248 char buf[MAX_CMD_SIZE] = {0};
4249 char cmd[MAX_CMD_SIZE] = {0};
4250 FILE *fp = NULL;
4251
4252 if (NULL == output_struct) {
4253 return RETURN_ERR;
4254 }
4255
4256 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4257
4258 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4259 {
4260 if(apIndex == 0) //private_wifi for 2.4G
4261 {
developerac6f1142022-12-20 19:26:35 +08004262 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004263 }
4264 else if(apIndex == 1) //private_wifi for 5G
4265 {
developerac6f1142022-12-20 19:26:35 +08004266 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004267 }
4268 else if(apIndex == 4) //public_wifi for 2.4G
4269 {
4270 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4271 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4272 {
4273 return RETURN_ERR;
4274 }
4275 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004276 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004277 else//tenda
developerac6f1142022-12-20 19:26:35 +08004278 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004279 }
4280 else if(apIndex == 5) //public_wifi for 5G
4281 {
developerac6f1142022-12-20 19:26:35 +08004282 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004283 }
4284
4285 GetIfacestatus(interface_name, interface_status);
4286
4287 if(0 != strcmp(interface_status, "1"))
4288 return RETURN_ERR;
4289
4290 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4291 system(cmd);
4292
4293 fp = fopen("/tmp/SSID_Stats.txt", "r");
4294 if(fp == NULL)
4295 {
4296 printf("/tmp/SSID_Stats.txt not exists \n");
4297 return RETURN_ERR;
4298 }
4299 fclose(fp);
4300
4301 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4302 File_Reading(buf, Value);
4303 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4304
4305 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4306 File_Reading(buf, Value);
4307 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4308
4309 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4310 File_Reading(buf, Value);
4311 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4312
4313 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4314 File_Reading(buf, Value);
4315 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4316
4317 /* There is no specific parameter from caller to associate the value wifi_Associations */
4318 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4319 //_syscmd(cmd, buf, sizeof(buf));
4320 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4321 }
4322#endif
4323 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4324 return RETURN_OK;
4325}
4326
4327INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4328{
4329 char interface_name[MAX_BUF_SIZE] = {0};
4330 char interface_status[MAX_BUF_SIZE] = {0};
4331 char Value[MAX_BUF_SIZE] = {0};
4332 char buf[MAX_CMD_SIZE] = {0};
4333 char cmd[MAX_CMD_SIZE] = {0};
4334 FILE *fp = NULL;
4335
4336 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4337 if (NULL == output_struct)
4338 return RETURN_ERR;
4339
4340 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4341
developerac6f1142022-12-20 19:26:35 +08004342 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004343 return RETURN_ERR;
4344 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004345
developerd946fd62022-12-08 18:03:28 +08004346 if(0 != strcmp(interface_status, "1"))
4347 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004348
developerd946fd62022-12-08 18:03:28 +08004349 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4350 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004351
developerd946fd62022-12-08 18:03:28 +08004352 fp = fopen("/tmp/SSID_Stats.txt", "r");
4353 if(fp == NULL)
4354 {
4355 printf("/tmp/SSID_Stats.txt not exists \n");
4356 return RETURN_ERR;
4357 }
4358 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004359
developerd946fd62022-12-08 18:03:28 +08004360 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4361 File_Reading(buf, Value);
4362 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004363
developerd946fd62022-12-08 18:03:28 +08004364 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4365 File_Reading(buf, Value);
4366 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004367
developerd946fd62022-12-08 18:03:28 +08004368 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4369 File_Reading(buf, Value);
4370 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004371
developerd946fd62022-12-08 18:03:28 +08004372 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4373 File_Reading(buf, Value);
4374 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004375
4376 output_struct->wifi_UnicastPacketsSent = 0;
4377 output_struct->wifi_UnicastPacketsReceived = 0;
4378 output_struct->wifi_MulticastPacketsSent = 0;
4379 output_struct->wifi_MulticastPacketsReceived = 0;
4380 output_struct->wifi_BroadcastPacketsSent = 0;
4381 output_struct->wifi_BroadcastPacketsRecevied = 0;
4382 output_struct->wifi_UnknownPacketsReceived = 0;
4383
4384 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4385 return RETURN_OK;
4386}
4387
4388INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4389{
4390 INT status = RETURN_ERR;
4391
4392 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4393 //Below values should get updated from hal
4394 output_struct->wifi_RetransCount=0;
4395 output_struct->wifi_FailedRetransCount=0;
4396 output_struct->wifi_RetryCount=0;
4397 output_struct->wifi_MultipleRetryCount=0;
4398 output_struct->wifi_ACKFailureCount=0;
4399 output_struct->wifi_AggregatedPacketCount=0;
4400
4401 status = RETURN_OK;
4402 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4403
4404 return status;
4405}
4406
4407INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4408{
4409 INT status = RETURN_ERR;
4410 UINT index;
4411 wifi_neighbor_ap_t *pt=NULL;
4412
4413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4414 *output_array_size=2;
4415 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4416 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4417 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4418 strcpy(pt->ap_Radio,"");
4419 strcpy(pt->ap_SSID,"");
4420 strcpy(pt->ap_BSSID,"");
4421 strcpy(pt->ap_Mode,"");
4422 pt->ap_Channel=1;
4423 pt->ap_SignalStrength=0;
4424 strcpy(pt->ap_SecurityModeEnabled,"");
4425 strcpy(pt->ap_EncryptionMode,"");
4426 strcpy(pt->ap_OperatingFrequencyBand,"");
4427 strcpy(pt->ap_SupportedStandards,"");
4428 strcpy(pt->ap_OperatingStandards,"");
4429 strcpy(pt->ap_OperatingChannelBandwidth,"");
4430 pt->ap_BeaconPeriod=1;
4431 pt->ap_Noise=0;
4432 strcpy(pt->ap_BasicDataTransferRates,"");
4433 strcpy(pt->ap_SupportedDataTransferRates,"");
4434 pt->ap_DTIMPeriod=1;
4435 pt->ap_ChannelUtilization = 1;
4436 }
4437
4438 status = RETURN_OK;
4439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4440
4441 return status;
4442}
4443
4444//----------------- AP HAL -------------------------------
4445
4446//>> Deprecated: used for old RDKB code.
4447INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4448{
4449 if (NULL == output_ulong || NULL == output_struct)
4450 return RETURN_ERR;
4451 *output_ulong = 0;
4452 *output_struct = NULL;
4453 return RETURN_OK;
4454}
4455
4456#ifdef HAL_NETLINK_IMPL
4457static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4458 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4459 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4460 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4461 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4462 char mac_addr[20];
4463 static int count=0;
4464 int rate=0;
4465
4466 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4467
4468 nla_parse(tb,
4469 NL80211_ATTR_MAX,
4470 genlmsg_attrdata(gnlh, 0),
4471 genlmsg_attrlen(gnlh, 0),
4472 NULL);
4473
4474 if(!tb[NL80211_ATTR_STA_INFO]) {
4475 fprintf(stderr, "sta stats missing!\n");
4476 return NL_SKIP;
4477 }
4478
4479
4480 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4481 fprintf(stderr, "failed to parse nested attributes!\n");
4482 return NL_SKIP;
4483 }
4484
4485 //devIndex starts from 1
4486 if( ++count == out->wifi_devIndex )
4487 {
4488 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4489 //Getting the mac addrress
4490 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4491
4492 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4493 fprintf(stderr, "failed to parse nested rate attributes!");
4494 return NL_SKIP;
4495 }
4496
4497 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4498 if(rinfo[NL80211_RATE_INFO_BITRATE])
4499 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4500 out->wifi_devTxRate = rate/10;
4501 }
4502
4503 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4504 fprintf(stderr, "failed to parse nested rate attributes!");
4505 return NL_SKIP;
4506 }
4507
4508 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4509 if(rinfo[NL80211_RATE_INFO_BITRATE])
4510 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4511 out->wifi_devRxRate = rate/10;
4512 }
4513 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4514 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4515
4516 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4517 count = 0; //starts the count for next cycle
4518 return NL_STOP;
4519 }
4520
4521 return NL_SKIP;
4522
4523}
4524#endif
4525
4526INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4527{
4528#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004529 Netlink nl = {0};
4530 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004531 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004532
developer30423732022-12-01 16:17:49 +08004533 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004534 info.wifi_devIndex = devIndex;
4535
developerac6f1142022-12-20 19:26:35 +08004536 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004537 return RETURN_ERR;
4538
4539 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004540
4541 nl.id = initSock80211(&nl);
4542
4543 if (nl.id < 0) {
4544 fprintf(stderr, "Error initializing netlink \n");
4545 return -1;
4546 }
4547
4548 struct nl_msg* msg = nlmsg_alloc();
4549
4550 if (!msg) {
4551 fprintf(stderr, "Failed to allocate netlink message.\n");
4552 nlfree(&nl);
4553 return -2;
4554 }
4555
4556 genlmsg_put(msg,
4557 NL_AUTO_PORT,
4558 NL_AUTO_SEQ,
4559 nl.id,
4560 0,
4561 NLM_F_DUMP,
4562 NL80211_CMD_GET_STATION,
4563 0);
4564
4565 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4566 nl_send_auto(nl.socket, msg);
4567 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4568 nl_recvmsgs(nl.socket, nl.cb);
4569 nlmsg_free(msg);
4570 nlfree(&nl);
4571
4572 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4573 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4574 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4575 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4576 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4577 return RETURN_OK;
4578#else
4579 //iw utility to retrieve station information
4580#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4581#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4582#define MACFILE "/tmp/wifi_AssoMac.txt"
4583#define TXRATEFILE "/tmp/wifi_txrate.txt"
4584#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4585 FILE *file = NULL;
4586 char if_name[10] = {'\0'};
4587 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004588 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004589 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004590 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004591
developerac6f1142022-12-20 19:26:35 +08004592 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004593 return RETURN_ERR;
4594
4595 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004596
4597 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4598 file = popen(pipeCmd, "r");
4599
4600 if(file == NULL)
4601 return RETURN_ERR; //popen failed
4602
4603 fgets(line, sizeof line, file);
4604 device = atoi(line);
4605 pclose(file);
4606
4607 if(device == 0)
4608 return RETURN_ERR; //No devices are connected
4609
4610 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4611 system(pipeCmd);
4612
4613 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4614
4615 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4616
4617 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4618
4619 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4620
4621 //devIndex starts from 1, ++count
4622 if((file = fopen(SIGNALFILE, "r")) != NULL )
4623 {
4624 for(count =0;fgets(line, sizeof line, file) != NULL;)
4625 {
4626 if (++count == devIndex)
4627 {
4628 output_struct->wifi_devSignalStrength = atoi(line);
4629 break;
4630 }
4631 }
4632 fclose(file);
4633 }
4634 else
4635 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4636
4637 if((file = fopen(MACFILE, "r")) != NULL )
4638 {
4639 for(count =0;fgets(line, sizeof line, file) != NULL;)
4640 {
4641 if (++count == devIndex)
4642 {
4643 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]);
4644 break;
4645 }
4646 }
4647 fclose(file);
4648 }
4649 else
4650 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4651
4652 if((file = fopen(TXRATEFILE, "r")) != NULL )
4653 {
4654 for(count =0;fgets(line, sizeof line, file) != NULL;)
4655 {
4656 if (++count == devIndex)
4657 {
4658 output_struct->wifi_devTxRate = atoi(line);
4659 break;
4660 }
4661 }
4662 fclose(file);
4663 }
4664 else
4665 fprintf(stderr,"fopen wifi_txrate.txt failed");
4666
4667 if((file = fopen(RXRATEFILE, "r")) != NULL)
4668 {
4669 for(count =0;fgets(line, sizeof line, file) != NULL;)
4670 {
4671 if (++count == devIndex)
4672 {
4673 output_struct->wifi_devRxRate = atoi(line);
4674 break;
4675 }
4676 }
4677 fclose(file);
4678 }
4679 else
4680 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4681
4682 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4683
4684 return RETURN_OK;
4685#endif
4686}
4687
4688INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4689{
4690 if (NULL == device)
4691 return RETURN_ERR;
4692 return RETURN_OK;
4693}
4694//<<
4695
4696
4697//--------------wifi_ap_hal-----------------------------
4698//enables CTS protection for the radio used by this AP
4699INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4700{
4701 //save config and Apply instantly
4702 return RETURN_ERR;
4703}
4704
4705// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4706INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4707{
developer463d39a2022-09-13 15:32:51 +08004708 char config_file[64] = {'\0'};
4709 char buf[64] = {'\0'};
4710 struct params list;
4711
4712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4713 list.name = "ht_coex";
4714 snprintf(buf, sizeof(buf), "%d", enable);
4715 list.value = buf;
4716
4717 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4718 wifi_hostapdWrite(config_file, &list, 1);
4719 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4720
4721 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4722
4723 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004724}
4725
4726//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4727INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4728{
developerea4bcce2022-09-13 15:26:13 +08004729 char config_file[MAX_BUF_SIZE] = {'\0'};
4730 char buf[MAX_BUF_SIZE] = {'\0'};
4731 struct params list;
4732
4733 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4734 if (threshold < 256 || threshold > 2346 )
4735 return RETURN_ERR;
4736 list.name = "fragm_threshold";
4737 snprintf(buf, sizeof(buf), "%d", threshold);
4738 list.value = buf;
4739
4740 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4741 wifi_hostapdWrite(config_file, &list, 1);
4742 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004743
developerea4bcce2022-09-13 15:26:13 +08004744 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004745
4746 return RETURN_OK;
4747}
4748
4749// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4750INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4751{
developer51a927d2022-09-13 15:42:22 +08004752 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004753 char cmd[512] = {'\0'};
4754 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004755 char stbc_config[16] = {'\0'};
4756 wifi_band band;
4757 int iterator = 0;
4758 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004759 int ant_count = 0;
4760 int ant_bitmap = 0;
4761 struct params list;
developer51a927d2022-09-13 15:42:22 +08004762
4763 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4764
4765 band = wifi_index_to_band(radioIndex);
4766 if (band == band_invalid)
4767 return RETURN_ERR;
4768
4769 if (band == band_2_4)
4770 iterator = 1;
4771 else if (band == band_5)
4772 iterator = 2;
4773 else
4774 return RETURN_OK;
4775
developer110b8a32022-12-26 15:56:44 +08004776 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4777 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4778 ant_count += ant_bitmap & 1;
4779
4780 if (ant_count == 1 && STBC_Enable == TRUE) {
4781 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4782 return RETURN_OK;
4783 }
4784
developer51a927d2022-09-13 15:42:22 +08004785 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4786
4787 // set ht and vht config
4788 for (int i = 0; i < iterator; i++) {
4789 memset(stbc_config, 0, sizeof(stbc_config));
4790 memset(cmd, 0, sizeof(cmd));
4791 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004792 list.name = (i == 0)?"ht_capab":"vht_capab";
4793 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004794 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4795 _syscmd(cmd, buf, sizeof(buf));
4796 if (strlen(buf) != 0)
4797 current_stbc = TRUE;
4798 if (current_stbc == STBC_Enable)
4799 continue;
4800
4801 if (STBC_Enable == TRUE) {
4802 // Append the STBC flags in capab config
4803 memset(cmd, 0, sizeof(cmd));
4804 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004805 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004806 else
developer6372c2b2022-10-27 17:39:51 +08004807 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 +08004808 _syscmd(cmd, buf, sizeof(buf));
4809 } else if (STBC_Enable == FALSE) {
4810 // Remove the STBC flags and remain other flags in capab
4811 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004812 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004813 _syscmd(cmd, buf, sizeof(buf));
4814 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004815 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004816 _syscmd(cmd, buf, sizeof(buf));
4817 }
developer110b8a32022-12-26 15:56:44 +08004818 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4819 list.value = buf;
4820 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004821 }
4822
4823 wifi_reloadAp(radioIndex);
4824
4825 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4826 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004827}
4828
4829// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4830INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4831{
developerfe7aefc2022-12-23 17:13:37 +08004832 char cmd[128] = {0};
4833 char buf[128] = {0};
4834 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004835
4836 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4837
4838 if(output_bool == NULL)
4839 return RETURN_ERR;
4840
developerfe7aefc2022-12-23 17:13:37 +08004841 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4842 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004843
developerfe7aefc2022-12-23 17:13:37 +08004844 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4845 _syscmd(cmd, buf, sizeof(buf));
4846
4847 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004848 *output_bool = TRUE;
4849 else
4850 *output_bool = FALSE;
4851
4852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4853 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004854}
4855
4856// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4857INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4858{
developerfe7aefc2022-12-23 17:13:37 +08004859 char config_file[128] = {0};
4860 struct params list = {0};
4861 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004862
4863 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4864
developerfe7aefc2022-12-23 17:13:37 +08004865 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004866 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004867
developerfe7aefc2022-12-23 17:13:37 +08004868 if (amsduEnable == enable)
4869 return RETURN_OK;
4870
4871 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4872 list.name = "amsdu";
4873 list.value = amsduEnable? "1":"0";
4874 wifi_hostapdWrite(config_file, &list, 1);
4875 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4876 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004877
4878 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4879 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004880}
4881
4882//P2 // outputs the number of Tx streams
4883INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4884{
developer2de97692022-09-26 14:00:03 +08004885 char buf[8] = {0};
4886 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004887 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004888
4889 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4890
developer033b37b2022-10-18 11:27:46 +08004891 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004892 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004893 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004894
developer110b8a32022-12-26 15:56:44 +08004895 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004896
4897 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4898
4899 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004900}
4901
developer110b8a32022-12-26 15:56:44 +08004902INT fitChainMask(INT radioIndex, int antcount)
4903{
4904 char buf[128] = {0};
4905 char cmd[128] = {0};
4906 char config_file[64] = {0};
4907 wifi_band band;
4908 struct params list[2] = {0};
4909
4910 band = wifi_index_to_band(radioIndex);
4911 if (band == band_invalid)
4912 return RETURN_ERR;
4913
4914 list[0].name = "he_mu_beamformer";
4915 list[1].name = "he_su_beamformer";
4916
4917 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4918 if (antcount == 1) {
4919 // remove config about multiple antennas
4920 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4921 _syscmd(cmd, buf, sizeof(buf));
4922
4923 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4924 _syscmd(cmd, buf, sizeof(buf));
4925
4926 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4927 _syscmd(cmd, buf, sizeof(buf));
4928
4929 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4930 _syscmd(cmd, buf, sizeof(buf));
4931
4932 list[0].value = "0";
4933 list[1].value = "0";
4934 } else {
4935 // 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.
4936 if (band == band_2_4 || band == band_5) {
4937 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4938 _syscmd(cmd, buf, sizeof(buf));
4939 if (strlen(buf) > 0) {
4940 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4941 _syscmd(cmd, buf, sizeof(buf));
4942 }
4943 }
4944 if (band == band_5) {
4945 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4946 _syscmd(cmd, buf, sizeof(buf));
4947 if (strlen(buf) > 0) {
4948 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4949 _syscmd(cmd, buf, sizeof(buf));
4950 }
4951 }
4952
4953 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4954 _syscmd(cmd, buf, sizeof(buf));
4955 if (strlen(buf) == 0) {
4956 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4957 _syscmd(cmd, buf, sizeof(buf));
4958 }
4959
4960 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4961 _syscmd(cmd, buf, sizeof(buf));
4962 if (strlen(buf) == 0) {
4963 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4964 _syscmd(cmd, buf, sizeof(buf));
4965 }
4966
4967 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4968 _syscmd(cmd, buf, sizeof(buf));
4969 if (strlen(buf) == 0) {
4970 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4971 } else {
4972 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4973 }
4974 _syscmd(cmd, buf, sizeof(buf));
4975
4976 list[0].value = "1";
4977 list[1].value = "1";
4978 }
4979 wifi_hostapdWrite(config_file, list, 2);
4980}
4981
developer06a01d92022-09-07 16:32:39 +08004982//P2 // sets the number of Tx streams to an enviornment variable
4983INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4984{
developer2de97692022-09-26 14:00:03 +08004985 char cmd[128] = {0};
4986 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004987 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08004988 int cur_mask = 0;
4989 int antcount = 0;
4990 wifi_band band;
developer2de97692022-09-26 14:00:03 +08004991
4992 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4993
developer110b8a32022-12-26 15:56:44 +08004994 if (numStreams <= 0) {
4995 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08004996 return RETURN_ERR;
4997 }
developer110b8a32022-12-26 15:56:44 +08004998
4999 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
5000 if (cur_mask == numStreams)
5001 return RETURN_OK;
5002
developer2de97692022-09-26 14:00:03 +08005003 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08005004
5005 phyId = radio_index_to_phy(radioIndex);
5006 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08005007 _syscmd(cmd, buf, sizeof(buf));
5008
5009 if (strlen(buf) > 0) {
5010 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5011 return RETURN_ERR;
5012 }
developer2de97692022-09-26 14:00:03 +08005013
developer110b8a32022-12-26 15:56:44 +08005014 // if chain mask changed, we need to make the hostapd config valid.
5015 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5016 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08005017 }
developer110b8a32022-12-26 15:56:44 +08005018 fitChainMask(radioIndex, antcount);
5019
5020 wifi_setRadioEnable(radioIndex, TRUE);
5021
developer2de97692022-09-26 14:00:03 +08005022 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5023 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005024}
5025
5026//P2 // outputs the number of Rx streams
5027INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5028{
developer110b8a32022-12-26 15:56:44 +08005029 char buf[8] = {0};
5030 char cmd[128] = {0};
5031 int phyId = 0;
5032
developer2de97692022-09-26 14:00:03 +08005033 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005034
5035 phyId = radio_index_to_phy(radioIndex);
5036 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5037 _syscmd(cmd, buf, sizeof(buf));
5038
5039 *output_int = (INT)strtol(buf, NULL, 16);
5040
developer2de97692022-09-26 14:00:03 +08005041 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005042
developer06a01d92022-09-07 16:32:39 +08005043 return RETURN_OK;
5044}
5045
5046//P2 // sets the number of Rx streams to an enviornment variable
5047INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5048{
developer2de97692022-09-26 14:00:03 +08005049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5050 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5051 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5052 return RETURN_ERR;
5053 }
5054 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005055 return RETURN_ERR;
5056}
5057
5058//Get radio RDG enable setting
5059INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5060{
5061 if (NULL == output_bool)
5062 return RETURN_ERR;
5063 *output_bool = TRUE;
5064 return RETURN_OK;
5065}
5066
5067//Get radio RDG enable setting
5068INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5069{
5070 if (NULL == output_bool)
5071 return RETURN_ERR;
5072 *output_bool = TRUE;
5073 return RETURN_OK;
5074}
5075
5076//Set radio RDG enable setting
5077INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5078{
5079 return RETURN_ERR;
5080}
5081
5082//Get radio ADDBA enable setting
5083INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5084{
5085 if (NULL == output_bool)
5086 return RETURN_ERR;
5087 *output_bool = TRUE;
5088 return RETURN_OK;
5089}
5090
5091//Set radio ADDBA enable setting
5092INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5093{
5094 return RETURN_ERR;
5095}
5096
5097//Get radio auto block ack enable setting
5098INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5099{
5100 if (NULL == output_bool)
5101 return RETURN_ERR;
5102 *output_bool = TRUE;
5103 return RETURN_OK;
5104}
5105
5106//Set radio auto block ack enable setting
5107INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5108{
5109 return RETURN_ERR;
5110}
5111
5112//Get radio 11n pure mode enable support
5113INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5114{
5115 if (NULL == output_bool)
5116 return RETURN_ERR;
5117 *output_bool = TRUE;
5118 return RETURN_OK;
5119}
5120
5121//Get radio 11n pure mode enable setting
5122INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5123{
5124 if (NULL == output_bool)
5125 return RETURN_ERR;
5126 *output_bool = TRUE;
5127 return RETURN_OK;
5128}
5129
5130//Set radio 11n pure mode enable setting
5131INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5132{
5133 return RETURN_ERR;
5134}
5135
5136//Get radio IGMP snooping enable setting
5137INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5138{
developerd946fd62022-12-08 18:03:28 +08005139 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005140 char cmd[128]={0};
5141 char buf[4]={0};
5142 bool bridge = FALSE, mac80211 = FALSE;
5143 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5144
5145 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005146 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005147
5148 *output_bool = FALSE;
5149
5150 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5151 _syscmd(cmd, buf, sizeof(buf));
5152 if (strncmp(buf, "1", 1) == 0)
5153 bridge = TRUE;
5154
developerac6f1142022-12-20 19:26:35 +08005155 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005156 return RETURN_ERR;
5157 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 +08005158 _syscmd(cmd, buf, sizeof(buf));
5159 if (strncmp(buf, "1", 1) == 0)
5160 mac80211 = TRUE;
5161
5162 if (bridge && mac80211)
5163 *output_bool = TRUE;
5164
5165 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005166 return RETURN_OK;
5167}
5168
5169//Set radio IGMP snooping enable setting
5170INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5171{
developerd946fd62022-12-08 18:03:28 +08005172 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005173 char cmd[128]={0};
5174 char buf[4]={0};
developer894affa2023-05-10 18:13:19 +08005175 int max_num_radios = 0;
5176 int apIndex = 0;
developer81bf2ed2022-09-13 15:31:14 +08005177 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5178
5179 // bridge
developerfb09ba62023-06-09 17:03:21 +08005180 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
developer81bf2ed2022-09-13 15:31:14 +08005181 _syscmd(cmd, buf, sizeof(buf));
5182
developer804c64f2022-10-19 13:54:40 +08005183 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005184 // mac80211
developer894affa2023-05-10 18:13:19 +08005185 for (int i = 0; i < MAX_NUM_VAP_PER_RADIO; i++) {
5186 apIndex = radioIndex + i*max_num_radios;
5187 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5188 continue;
developerfb09ba62023-06-09 17:03:21 +08005189 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 +08005190 _syscmd(cmd, buf, sizeof(buf));
5191 }
5192 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5193 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005194}
5195
5196//Get the Reset count of radio
5197INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5198{
5199 if (NULL == output_int)
5200 return RETURN_ERR;
5201 *output_int = (radioIndex==0)? 1: 3;
5202
5203 return RETURN_OK;
5204}
5205
5206
5207//---------------------------------------------------------------------------------------------------
5208//
5209// Additional Wifi AP level APIs used for Access Point devices
5210//
5211//---------------------------------------------------------------------------------------------------
5212
5213// creates a new ap and pushes these parameters to the hardware
5214INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5215{
developer7930d352022-12-21 17:55:42 +08005216 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005217 return RETURN_OK;
5218}
5219
5220// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5221INT wifi_deleteAp(INT apIndex)
5222{
developerd946fd62022-12-08 18:03:28 +08005223 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005224 char buf[128] = {0};
5225 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005226
developerac6f1142022-12-20 19:26:35 +08005227 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005228 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005229
developer89df4502023-02-16 20:45:02 +08005230 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5231 return RETURN_ERR;
5232
developer7930d352022-12-21 17:55:42 +08005233 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005234 _syscmd(cmd, buf, sizeof(buf));
5235
5236 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005237 return RETURN_OK;
5238}
5239
5240// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5241INT wifi_getApName(INT apIndex, CHAR *output_string)
5242{
developerd946fd62022-12-08 18:03:28 +08005243 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005244 if(NULL == output_string)
5245 return RETURN_ERR;
5246
developerac6f1142022-12-20 19:26:35 +08005247 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005248 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005249 else
5250 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005251 return RETURN_OK;
5252}
5253
5254// Outputs the index number in that corresponds to the SSID string
5255INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5256{
developerd946fd62022-12-08 18:03:28 +08005257 char cmd [128] = {0};
5258 char buf[32] = {0};
5259 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005260 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005261
developerd946fd62022-12-08 18:03:28 +08005262 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5263 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005264
developerac6f1142022-12-20 19:26:35 +08005265 if (strlen(buf) != 0) {
5266 apIndex_str = strtok(buf, "\n");
5267 *output_int = strtoul(apIndex_str, NULL, 10);
5268 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005269 }
developer67b8ee92022-12-20 10:48:43 +08005270
5271 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5272 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5273 if (apIndex_str) {
5274 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5275 return RETURN_OK;
5276 }
developerd946fd62022-12-08 18:03:28 +08005277 *output_int = -1;
5278 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005279}
5280
5281INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5282{
5283 return wifi_getIndexFromName(inputSsidString, output_int);
5284}
5285
5286// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5287INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5288{
5289 char buf[MAX_BUF_SIZE] = {0};
5290 char cmd[MAX_CMD_SIZE] = {0};
5291 char config_file[MAX_BUF_SIZE] = {0};
5292
5293 if(NULL == output_string)
5294 return RETURN_ERR;
5295
5296 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5297 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5298 if((strcmp(buf,"3")==0))
5299 snprintf(output_string, 32, "WPAand11i");
5300 else if((strcmp(buf,"2")==0))
5301 snprintf(output_string, 32, "11i");
5302 else if((strcmp(buf,"1")==0))
5303 snprintf(output_string, 32, "WPA");
5304 else
5305 snprintf(output_string, 32, "None");
5306
5307 return RETURN_OK;
5308}
5309
5310// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5311INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5312{
5313 char config_file[MAX_BUF_SIZE] = {0};
5314 struct params list;
5315
5316 if (NULL == beaconTypeString)
5317 return RETURN_ERR;
5318 list.name = "wpa";
5319 list.value = "0";
5320
5321 if((strcmp(beaconTypeString,"WPAand11i")==0))
5322 list.value="3";
5323 else if((strcmp(beaconTypeString,"11i")==0))
5324 list.value="2";
5325 else if((strcmp(beaconTypeString,"WPA")==0))
5326 list.value="1";
5327
5328 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5329 wifi_hostapdWrite(config_file, &list, 1);
5330 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5331 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5332 return RETURN_OK;
5333}
5334
5335// sets the beacon interval on the hardware for this AP
5336INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5337{
developer5f222492022-09-13 15:21:52 +08005338 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5339 struct params params={'\0'};
5340 char buf[MAX_BUF_SIZE] = {'\0'};
5341 char config_file[MAX_BUF_SIZE] = {'\0'};
5342
5343 params.name = "beacon_int";
5344 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5345 params.value = buf;
5346
5347 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5348 wifi_hostapdWrite(config_file, &params, 1);
5349
5350 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5351 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5352 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005353}
5354
5355INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5356{
developer5b398df2022-11-17 20:39:48 +08005357 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5358 return RETURN_ERR;
5359 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005360}
5361
5362// Get the packet size threshold supported.
5363INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5364{
5365 //save config and apply instantly
5366 if (NULL == output_bool)
5367 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005368 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005369 return RETURN_OK;
5370}
5371
5372// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5373INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5374{
developer514406b2022-12-05 17:20:21 +08005375 char buf[16] = {0};
5376 char config_file[128] = {0};
5377 struct params param = {0};
5378
5379 if (threshold > 65535) {
5380 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5381 return RETURN_ERR;
5382 }
developer06a01d92022-09-07 16:32:39 +08005383
developer23e71282023-01-18 10:25:19 +08005384 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005385 snprintf(buf, sizeof(buf), "%u", threshold);
5386 param.name = "rts_threshold";
5387 param.value = buf;
5388 wifi_hostapdWrite(config_file, &param, 1);
5389 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5390 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005391
5392 return RETURN_OK;
5393}
5394
5395// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5396INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5397{
5398 if (NULL == output_string)
5399 return RETURN_ERR;
5400 snprintf(output_string, 32, "TKIPandAESEncryption");
5401 return RETURN_OK;
5402
5403}
5404
5405// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5406INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5407{
5408 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005409 char *param_name = NULL;
5410 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005411
5412 if(NULL == output_string)
5413 return RETURN_ERR;
5414
5415 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5416 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5417
5418 if(strcmp(buf,"0")==0)
5419 {
5420 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5421 snprintf(output_string, 32, "None");
5422 return RETURN_OK;
5423 }
5424 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5425 param_name = "rsn_pairwise";
5426 else if((strcmp(buf,"1")==0))
5427 param_name = "wpa_pairwise";
5428 else
5429 return RETURN_ERR;
5430 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005431 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005432 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5433 param_name = "wpa_pairwise";
5434 memset(output_string, '\0', 32);
5435 wifi_hostapdRead(config_file, param_name, output_string, 32);
5436 }
developer06a01d92022-09-07 16:32:39 +08005437 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5438
developer72ec5572023-01-05 16:27:13 +08005439 if(strcmp(output_string,"TKIP CCMP") == 0)
5440 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5441 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005442 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5443 else if(strcmp(output_string,"CCMP") == 0)
5444 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005445
5446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5447 return RETURN_OK;
5448}
5449
5450// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5451INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5452{
5453 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5454 struct params params={'\0'};
5455 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005456 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005457
5458 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005459 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005460
5461 if(strcmp(encMode, "TKIPEncryption") == 0)
5462 params.value = "TKIP";
5463 else if(strcmp(encMode,"AESEncryption") == 0)
5464 params.value = "CCMP";
5465 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5466 params.value = "TKIP CCMP";
5467
5468 if((strcmp(output_string,"WPAand11i")==0))
5469 {
5470 params.name = "wpa_pairwise";
5471 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5472 wifi_hostapdWrite(config_file, &params, 1);
5473 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5474
developer30423732022-12-01 16:17:49 +08005475 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005476 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5477 wifi_hostapdWrite(config_file, &params, 1);
5478 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5479
5480 return RETURN_OK;
5481 }
5482 else if((strcmp(output_string,"11i")==0))
5483 {
5484 params.name = "rsn_pairwise";
5485 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5486 wifi_hostapdWrite(config_file, &params, 1);
5487 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5488 return RETURN_OK;
5489 }
5490 else if((strcmp(output_string,"WPA")==0))
5491 {
5492 params.name = "wpa_pairwise";
5493 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5494 wifi_hostapdWrite(config_file, &params, 1);
5495 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5496 return RETURN_OK;
5497 }
5498
5499 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5500 return RETURN_OK;
5501}
5502
5503// deletes internal security varable settings for this ap
5504INT wifi_removeApSecVaribles(INT apIndex)
5505{
5506 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005507 //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 +08005508 //_syscmd(cmd, buf, sizeof(buf));
5509
developerd946fd62022-12-08 18:03:28 +08005510 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005511 //_syscmd(cmd, buf, sizeof(buf));
5512 return RETURN_ERR;
5513}
5514
5515// changes the hardware settings to disable encryption on this ap
5516INT wifi_disableApEncryption(INT apIndex)
5517{
5518 //Apply instantly
5519 return RETURN_ERR;
5520}
5521
5522// set the authorization mode on this ap
5523// mode mapping as: 1: open, 2: shared, 4:auto
5524INT wifi_setApAuthMode(INT apIndex, INT mode)
5525{
developeraf95c502022-09-13 16:18:22 +08005526 struct params params={0};
5527 char config_file[64] = {0};
5528 int ret;
5529
5530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5531
5532 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5533 params.name = "auth_algs";
5534
developer72ec5572023-01-05 16:27:13 +08005535 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005536 params.value = "3";
5537 else if (mode & 2)
5538 params.value = "2";
5539 else if (mode & 1)
5540 params.value = "1";
5541 else
5542 params.value = "0";
5543
5544 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5545 wifi_hostapdWrite(config_file, &params, 1);
5546 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005547 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005548 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5549
5550 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005551}
5552
5553// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5554INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5555{
5556 //save to wifi config, and wait for wifi restart to apply
5557 struct params params={'\0'};
5558 char config_file[MAX_BUF_SIZE] = {0};
5559 int ret;
5560
5561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5562 if(authMode == NULL)
5563 return RETURN_ERR;
5564
5565 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5566 params.name = "wpa_key_mgmt";
5567
5568 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5569 params.value = "WPA-PSK";
5570 else if(strcmp(authMode,"EAPAuthentication") == 0)
5571 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005572 else if (strcmp(authMode, "SAEAuthentication") == 0)
5573 params.value = "SAE";
5574 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5575 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005576 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5577 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005578 else if (strcmp(authMode, "Enhanced_Open") == 0)
5579 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005580 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5581 return RETURN_OK; //This is taken careof in beaconType
5582
5583 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5584 ret=wifi_hostapdWrite(config_file,&params,1);
5585 if(!ret)
5586 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5587 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5588
5589 return ret;
5590}
5591
5592// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5593INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5594{
5595 //save to wifi config, and wait for wifi restart to apply
5596 char BeaconType[50] = {0};
5597 char config_file[MAX_BUF_SIZE] = {0};
5598
5599 *authMode = 0;
5600 wifi_getApBeaconType(apIndex,BeaconType);
5601 printf("%s____%s \n",__FUNCTION__,BeaconType);
5602
5603 if(strcmp(BeaconType,"None") == 0)
5604 strcpy(authMode,"None");
5605 else
5606 {
5607 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5608 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5609 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5610 if(strcmp(authMode,"WPA-PSK") == 0)
5611 strcpy(authMode,"SharedAuthentication");
5612 else if(strcmp(authMode,"WPA-EAP") == 0)
5613 strcpy(authMode,"EAPAuthentication");
5614 }
5615
5616 return RETURN_OK;
5617}
5618
5619// Outputs the number of stations associated per AP
5620INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5621{
developerd946fd62022-12-08 18:03:28 +08005622 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005623 char cmd[128]={0};
5624 char buf[128]={0};
5625 BOOL status = false;
5626
5627 if(apIndex > MAX_APS)
5628 return RETURN_ERR;
5629
5630 wifi_getApEnable(apIndex,&status);
5631 if (!status)
5632 return RETURN_OK;
5633
developerd946fd62022-12-08 18:03:28 +08005634 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005635 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005636 return RETURN_ERR;
5637 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005638 _syscmd(cmd, buf, sizeof(buf));
5639 sscanf(buf,"%lu", output_ulong);
5640
5641 return RETURN_OK;
5642}
5643
5644// manually removes any active wi-fi association with the device specified on this ap
5645INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5646{
developerd946fd62022-12-08 18:03:28 +08005647 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005648 char buf[126]={'\0'};
5649
developerac6f1142022-12-20 19:26:35 +08005650 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005651 return RETURN_ERR;
5652 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005653 system(buf);
5654
5655 return RETURN_OK;
5656}
5657
5658// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5659INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5660{
5661 if(NULL == output_int)
5662 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005663 int max_radio_num = 0;
5664 wifi_getMaxRadioNumber(&max_radio_num);
5665 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005666 return RETURN_OK;
5667}
5668
5669// sets the radio index for the specific ap
5670INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5671{
5672 //set to config only and wait for wifi reset to apply settings
5673 return RETURN_ERR;
5674}
5675
5676// Get the ACL MAC list per AP
5677INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5678{
developerd946fd62022-12-08 18:03:28 +08005679 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005680 char cmd[MAX_CMD_SIZE]={'\0'};
5681 int ret = 0;
5682
developerac6f1142022-12-20 19:26:35 +08005683 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005684 return RETURN_ERR;
5685 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005686 ret = _syscmd(cmd,macArray,buf_size);
5687 if (ret != 0)
5688 return RETURN_ERR;
5689
5690 return RETURN_OK;
5691}
5692
developere6aafda2022-09-13 14:59:28 +08005693INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5694{
developerd946fd62022-12-08 18:03:28 +08005695 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005696 char cmd[MAX_CMD_SIZE]={'\0'};
5697 int ret = 0;
5698
developerac6f1142022-12-20 19:26:35 +08005699 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005700 return RETURN_ERR;
5701 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005702 ret = _syscmd(cmd,macArray,buf_size);
5703 if (ret != 0)
5704 return RETURN_ERR;
5705
5706 return RETURN_OK;
5707}
5708
developer06a01d92022-09-07 16:32:39 +08005709// Get the list of stations associated per AP
5710INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5711{
developerd946fd62022-12-08 18:03:28 +08005712 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005713 char cmd[128];
5714
5715 if(apIndex > 3) //Currently supporting apIndex upto 3
5716 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005717 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005718 return RETURN_ERR;
5719 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5720 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005721 _syscmd(cmd, macArray, buf_size);
5722
5723 return RETURN_OK;
5724}
5725
developer2f995fb2023-02-24 10:40:44 +08005726INT getAddressControlMode(INT apIndex, INT *mode)
5727{
5728 char buf [16] = {0};
5729 char config_file[64] = {0};
5730
5731 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5732 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5733
5734 *mode = -1;
5735 // 0 use deny file, 1 use accept file
5736 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5737 *mode = (INT)strtol(buf, NULL, 10);
5738
5739 return RETURN_OK;
5740}
5741
developer06a01d92022-09-07 16:32:39 +08005742// adds the mac address to the filter list
5743//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5744INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5745{
5746 char cmd[MAX_CMD_SIZE]={'\0'};
5747 char buf[MAX_BUF_SIZE]={'\0'};
5748
developer2f995fb2023-02-24 10:40:44 +08005749 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005750 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005751
developer06a01d92022-09-07 16:32:39 +08005752 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5753 if(_syscmd(cmd,buf,sizeof(buf)))
5754 return RETURN_ERR;
5755
5756 return RETURN_OK;
5757}
5758
developer2f995fb2023-02-24 10:40:44 +08005759INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5760{
5761 char cmd[MAX_CMD_SIZE]={'\0'};
5762 char buf[MAX_BUF_SIZE]={'\0'};
5763
5764 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5765 return RETURN_ERR;
5766
5767 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5768 if(_syscmd(cmd,buf,sizeof(buf)))
5769 return RETURN_ERR;
5770
5771 return RETURN_OK;
5772}
5773
developer06a01d92022-09-07 16:32:39 +08005774// deletes the mac address from the filter list
5775//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5776INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5777{
5778 char cmd[MAX_CMD_SIZE]={'\0'};
5779 char buf[MAX_BUF_SIZE]={'\0'};
5780
5781#if 0
developerd946fd62022-12-08 18:03:28 +08005782 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005783 if(_syscmd(cmd,buf,sizeof(buf)))
5784 return RETURN_ERR;
5785
5786#endif
developer2f995fb2023-02-24 10:40:44 +08005787 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005788 if(_syscmd(cmd,buf,sizeof(buf)))
5789 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005790 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5791 if(_syscmd(cmd,buf,sizeof(buf)))
5792 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005793
5794 return RETURN_OK;
5795}
5796
5797// outputs the number of devices in the filter list
5798INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5799{
developere6aafda2022-09-13 14:59:28 +08005800 char cmd[MAX_BUF_SIZE]={0};
5801 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005802 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005803
5804 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5805 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005806 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005807
developer2f995fb2023-02-24 10:40:44 +08005808 getAddressControlMode(apIndex, &mode);
5809 if (mode == -1)
5810 return RETURN_OK;
5811
5812 if (mode == 0)
5813 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5814 else if (mode == 1)
5815 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005816 _syscmd(cmd, buf, sizeof(buf));
5817
developer2f995fb2023-02-24 10:40:44 +08005818 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005819
5820 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5821 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005822}
5823
5824INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5825{
5826 char cmd[128]={'\0'};
5827 char buf[128]={'\0'};
5828
5829 if(strcmp(action,"DENY")==0)
5830 {
5831 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5832 system(buf);
5833 return RETURN_OK;
5834 }
5835
5836 if(strcmp(action,"ALLOW")==0)
5837 {
5838 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5839 system(buf);
5840 return RETURN_OK;
5841 }
5842
5843 return RETURN_ERR;
5844
5845}
5846
5847// enable kick for devices on acl black list
5848INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5849{
5850 char aclArray[512] = {0}, *acl = NULL;
5851 char assocArray[512] = {0}, *asso = NULL;
5852
developere6aafda2022-09-13 14:59:28 +08005853 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005854 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5855
5856 // if there are no devices connected there is nothing to do
5857 if (strlen(assocArray) < 17)
5858 return RETURN_OK;
5859
5860 if (enable == TRUE)
5861 {
5862 //kick off the MAC which is in ACL array (deny list)
5863 acl = strtok(aclArray, "\r\n");
5864 while (acl != NULL) {
5865 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5866 wifi_kickApAssociatedDevice(apIndex, acl);
5867
5868 acl = strtok(NULL, "\r\n");
5869 }
developere6aafda2022-09-13 14:59:28 +08005870 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005871 }
5872 else
5873 {
developere6aafda2022-09-13 14:59:28 +08005874 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005875 }
5876
5877#if 0
5878 //TODO: need to revisit below implementation
5879 char aclArray[512]={0}, *acl=NULL;
5880 char assocArray[512]={0}, *asso=NULL;
5881 char buf[256]={'\0'};
5882 char action[10]={'\0'};
5883 FILE *fr=NULL;
5884 char interface[10]={'\0'};
5885 char config_file[MAX_BUF_SIZE] = {0};
5886
5887 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5888 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5889 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5890 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5891
5892 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5893 system(buf);
5894 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5895 system(buf);
5896 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5897 system(buf);
5898 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5899 system(buf);
5900 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5901 system(buf);
5902
5903 if ( enable == TRUE )
5904 {
5905 int device_count=0;
5906 strcpy(action,"DENY");
5907 //kick off the MAC which is in ACL array (deny list)
5908 acl = strtok (aclArray,",");
5909 while (acl != NULL) {
5910 if(strlen(acl)>=17)
5911 {
5912 apply_rules(apIndex, acl,action,interface);
5913 device_count++;
5914 //Register mac to be blocked ,in syscfg.db persistent storage
5915 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5916 system(buf);
5917 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5918 system(buf);
5919 system("syscfg commit");
5920
5921 wifi_kickApAssociatedDevice(apIndex, acl);
5922 }
5923 acl = strtok (NULL, ",");
5924 }
5925 }
5926 else
5927 {
5928 int device_count=0;
5929 char cmdmac[20]={'\0'};
5930 strcpy(action,"ALLOW");
5931 //kick off the MAC which is not in ACL array (allow list)
5932 acl = strtok (aclArray,",");
5933 while (acl != NULL) {
5934 if(strlen(acl)>=17)
5935 {
5936 apply_rules(apIndex, acl,action,interface);
5937 device_count++;
5938 //Register mac to be Allowed ,in syscfg.db persistent storage
5939 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5940 system(buf);
5941 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5942 system(buf);
5943 sprintf(cmdmac,"%s",acl);
5944 }
5945 acl = strtok (NULL, ",");
5946 }
5947 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5948 system(buf);
5949
5950 //Disconnect the mac which is not in ACL
5951 asso = strtok (assocArray,",");
5952 while (asso != NULL) {
5953 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5954 wifi_kickApAssociatedDevice(apIndex, asso);
5955 asso = strtok (NULL, ",");
5956 }
5957 }
5958#endif
5959 return RETURN_OK;
5960}
5961
5962INT wifi_setPreferPrivateConnection(BOOL enable)
5963{
developer06a01d92022-09-07 16:32:39 +08005964 return RETURN_OK;
5965}
5966
5967// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5968INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5969{
developerd946fd62022-12-08 18:03:28 +08005970 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005971 int items = 1;
5972 struct params list[2];
5973 char buf[MAX_BUF_SIZE] = {0};
5974 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005975 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005976
5977 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005978
developer10adcc12022-09-13 14:39:17 +08005979 if (filterMode == 0) {
5980 sprintf(buf, "%d", 0);
5981 list[0].value = buf;
5982
developer2f995fb2023-02-24 10:40:44 +08005983 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08005984 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005985 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005986 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
5987 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08005988 memset(cmd,0,sizeof(cmd));
5989 // Delete deny_mac_file in hostapd configuration
5990 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08005991 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08005992 }
5993 else if (filterMode == 1) {
5994 sprintf(buf, "%d", filterMode);
5995 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005996 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5997 list[1].name = "accept_mac_file";
5998 list[1].value = acl_file;
5999 items = 2;
developer10adcc12022-09-13 14:39:17 +08006000 } else if (filterMode == 2) {
6001 //TODO: deny_mac_file
6002 sprintf(buf, "%d", 0);
6003 list[0].value = buf;
6004 list[1].name = "deny_mac_file";
6005 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
6006 list[1].value = deny_file;
6007 items = 2;
6008 } else {
6009 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006010 }
developer10adcc12022-09-13 14:39:17 +08006011
developer06a01d92022-09-07 16:32:39 +08006012 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6013 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08006014 if (multiple_set == FALSE) {
6015 wifi_setApEnable(apIndex, FALSE);
6016 wifi_setApEnable(apIndex, TRUE);
6017 }
developer06a01d92022-09-07 16:32:39 +08006018
6019 return RETURN_OK;
6020
6021#if 0
6022 if(apIndex==0 || apIndex==1)
6023 {
6024 //set the filtermode
6025 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
6026 system(buf);
6027 system("syscfg commit");
6028
6029 if(filterMode==0)
6030 {
6031 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6032 system(buf);
6033 return RETURN_OK;
6034 }
6035 }
6036 return RETURN_OK;
6037#endif
6038}
6039
6040// 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.
6041INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6042{
6043 return RETURN_ERR;
6044}
6045
6046// gets the vlan ID for this ap from an internal enviornment variable
6047INT wifi_getApVlanID(INT apIndex, INT *output_int)
6048{
developer30423732022-12-01 16:17:49 +08006049 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08006050 {
6051 *output_int=100;
6052 return RETURN_OK;
6053 }
6054
6055 return RETURN_ERR;
6056}
6057
6058// sets the vlan ID for this ap to an internal enviornment variable
6059INT wifi_setApVlanID(INT apIndex, INT vlanId)
6060{
6061 //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)
6062 return RETURN_ERR;
6063}
6064
6065// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6066INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6067{
6068 snprintf(bridgeName, 32, "brlan0");
6069 snprintf(IP, 32, "10.0.0.1");
6070 snprintf(subnet, 32, "255.255.255.0");
6071
6072 return RETURN_OK;
6073}
6074
6075//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6076INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6077{
6078 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6079 return RETURN_ERR;
6080}
6081
6082// reset the vlan configuration for this ap
6083INT wifi_resetApVlanCfg(INT apIndex)
6084{
developerf5fef612022-09-20 19:38:26 +08006085 char original_config_file[64] = {0};
6086 char current_config_file[64] = {0};
6087 char buf[64] = {0};
6088 char cmd[64] = {0};
6089 char vlan_file[64] = {0};
6090 char vlan_tagged_interface[16] = {0};
6091 char vlan_bridge[16] = {0};
6092 char vlan_naming[16] = {0};
6093 struct params list[4] = {0};
6094 wifi_band band;
6095
6096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6097
6098 band = wifi_index_to_band(apIndex);
6099 if (band == band_2_4)
6100 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006101 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006102 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006103 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006104 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6105
6106 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6107
6108 if (strlen(vlan_file) == 0)
6109 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006110
developerf5fef612022-09-20 19:38:26 +08006111 // The file should exist or this vap would not work.
6112 if (access(vlan_file, F_OK) != 0) {
6113 sprintf(cmd, "touch %s", vlan_file);
6114 _syscmd(cmd, buf, sizeof(buf));
6115 }
6116 list[0].name = "vlan_file";
6117 list[0].value = vlan_file;
6118
6119 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6120 list[1].name = "vlan_tagged_interface";
6121 list[1].value = vlan_tagged_interface;
6122
6123 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6124 list[2].name = "vlan_bridge";
6125 list[2].value = vlan_bridge;
6126
6127 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6128 list[3].name = "vlan_naming";
6129 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006130
developerf5fef612022-09-20 19:38:26 +08006131 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6132 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006133 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006134 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006135
developerf5fef612022-09-20 19:38:26 +08006136 // restart this ap
6137 wifi_setApEnable(apIndex, FALSE);
6138 wifi_setApEnable(apIndex, TRUE);
6139
6140 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6141
6142 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006143}
6144
6145// 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.
6146INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6147{
6148 return RETURN_ERR;
6149}
6150
6151// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6152INT wifi_startHostApd()
6153{
6154 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6155 system("systemctl start hostapd.service");
6156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6157 return RETURN_OK;
6158 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6159}
6160
6161// stops hostapd
6162INT wifi_stopHostApd()
6163{
6164 char cmd[128] = {0};
6165 char buf[128] = {0};
6166
6167 sprintf(cmd,"systemctl stop hostapd");
6168 _syscmd(cmd, buf, sizeof(buf));
6169
6170 return RETURN_OK;
6171}
6172
6173// restart hostapd dummy function
6174INT wifi_restartHostApd()
6175{
6176 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6177 system("systemctl restart hostapd-global");
6178 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6179
6180 return RETURN_OK;
6181}
6182
6183static int align_hostapd_config(int index)
6184{
6185 ULONG lval;
6186 wifi_getRadioChannel(index%2, &lval);
6187 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006188 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006189}
6190
6191// sets the AP enable status variable for the specified ap.
6192INT wifi_setApEnable(INT apIndex, BOOL enable)
6193{
developerd946fd62022-12-08 18:03:28 +08006194 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006195 char config_file[MAX_BUF_SIZE] = {0};
6196 char cmd[MAX_CMD_SIZE] = {0};
6197 char buf[MAX_BUF_SIZE] = {0};
6198 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006199 int max_radio_num = 0;
6200 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006201
6202 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006203
6204 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006205 if (enable == status)
6206 return RETURN_OK;
6207
developerac6f1142022-12-20 19:26:35 +08006208 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006209 return RETURN_ERR;
6210
developer06a01d92022-09-07 16:32:39 +08006211 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006212 int radioIndex = apIndex % max_radio_num;
6213 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006214 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6215 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006216 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006217 _syscmd(cmd, buf, sizeof(buf));
developer2f18b9f2023-03-17 19:32:57 +08006218 if (!(apIndex/max_radio_num)) {
6219 sprintf(cmd, "iw %s del", interface_name);
6220 _syscmd(cmd, buf, sizeof(buf));
6221 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6222 _syscmd(cmd, buf, sizeof(buf));
6223 }
developer033b37b2022-10-18 11:27:46 +08006224 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006225 _syscmd(cmd, buf, sizeof(buf));
6226 }
6227 else {
developerd946fd62022-12-08 18:03:28 +08006228 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006229 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006230 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006231 _syscmd(cmd, buf, sizeof(buf));
6232 }
developera77d84b2023-02-22 16:10:50 +08006233
developer431128d2022-12-16 15:30:41 +08006234 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006235 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006236 _syscmd(cmd, buf, sizeof(buf));
6237 //Wait for wifi up/down to apply
6238 return RETURN_OK;
6239}
6240
6241// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6242INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6243{
developerd946fd62022-12-08 18:03:28 +08006244 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006245 char cmd[MAX_CMD_SIZE] = {'\0'};
6246 char buf[MAX_BUF_SIZE] = {'\0'};
6247
6248 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6249 return RETURN_ERR;
6250
6251 *output_bool = 0;
6252
6253 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6254 {
developerac6f1142022-12-20 19:26:35 +08006255 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006256 *output_bool = FALSE;
6257 return RETURN_OK;
6258 }
6259 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006260 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6261 }
6262
6263 return RETURN_OK;
6264}
6265
6266// Outputs the AP "Enabled" "Disabled" status from driver
6267INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6268{
6269 char cmd[128] = {0};
6270 char buf[128] = {0};
6271 BOOL output_bool;
6272
6273 if ( NULL == output_string)
6274 return RETURN_ERR;
6275 wifi_getApEnable(apIndex,&output_bool);
6276
6277 if(output_bool == 1)
6278 snprintf(output_string, 32, "Up");
6279 else
6280 snprintf(output_string, 32, "Disable");
6281
6282 return RETURN_OK;
6283}
6284
6285//Indicates whether or not beacons include the SSID name.
6286// outputs a 1 if SSID on the AP is enabled, else outputs 0
6287INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6288{
6289 //get the running status
6290 char config_file[MAX_BUF_SIZE] = {0};
6291 char buf[16] = {0};
6292
6293 if (!output)
6294 return RETURN_ERR;
6295
6296 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6297 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006298 // default is enable
6299 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6300 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006301
6302 return RETURN_OK;
6303}
6304
6305// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6306INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6307{
6308 //store the config, apply instantly
6309 char config_file[MAX_BUF_SIZE] = {0};
6310 struct params list;
6311
6312 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6313 list.name = "ignore_broadcast_ssid";
6314 list.value = enable?"0":"1";
6315
6316 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6317 wifi_hostapdWrite(config_file, &list, 1);
6318 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6319 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006320 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08006321 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6322
6323 return RETURN_OK;
6324}
6325
6326//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6327INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6328{
6329 //get the running status
6330 if(!output_uint)
6331 return RETURN_ERR;
6332 *output_uint=16;
6333 return RETURN_OK;
6334}
6335
6336INT wifi_setApRetryLimit(INT apIndex, UINT number)
6337{
6338 //apply instantly
6339 return RETURN_ERR;
6340}
6341
6342//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6343INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6344{
6345 if(!output)
6346 return RETURN_ERR;
6347 *output=TRUE;
6348 return RETURN_OK;
6349}
6350
6351//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6352INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6353{
6354 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006355 char cmd[128] = {0};
6356 char buf[128] = {0};
6357 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006358 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006359
developer0b246d12022-09-30 15:24:20 +08006360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006361
developer0b246d12022-09-30 15:24:20 +08006362 wifi_getMaxRadioNumber(&max_radio_num);
6363 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006364 phyId = radio_index_to_phy(radioIndex);
6365 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006366 _syscmd(cmd,buf, sizeof(buf));
6367
6368 if (strlen(buf) > 0)
6369 *output = true;
6370
6371 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006372
developer06a01d92022-09-07 16:32:39 +08006373 return RETURN_OK;
6374}
6375
6376//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6377INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6378{
6379 //get the running status from driver
6380 if(!output)
6381 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006382
6383 char config_file[MAX_BUF_SIZE] = {0};
6384 char buf[16] = {0};
6385
6386 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6387 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006388 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006389 *output = TRUE;
6390 else
6391 *output = FALSE;
6392
developer06a01d92022-09-07 16:32:39 +08006393 return RETURN_OK;
6394}
6395
6396// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6397INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6398{
6399 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006400 char config_file[MAX_BUF_SIZE] = {0};
6401 struct params list;
6402
6403 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6404 list.name = "wmm_enabled";
6405 list.value = enable?"1":"0";
6406
6407 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6408 wifi_hostapdWrite(config_file, &list, 1);
6409 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6410 wifi_reloadAp(apIndex);
6411 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6412
6413 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006414}
6415
6416//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.
6417INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6418{
6419 //get the running status from driver
6420 if(!output)
6421 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006422
6423 char config_file[128] = {0};
6424 char buf[16] = {0};
6425
6426 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6427 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6428 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6429 *output = TRUE;
6430 else
6431 *output = FALSE;
6432
developer06a01d92022-09-07 16:32:39 +08006433 return RETURN_OK;
6434}
6435
6436// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6437INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6438{
6439 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006440 char config_file[MAX_BUF_SIZE] = {0};
6441 struct params list;
6442
6443 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6444 list.name = "uapsd_advertisement_enabled";
6445 list.value = enable?"1":"0";
6446
6447 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6448 wifi_hostapdWrite(config_file, &list, 1);
6449 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6450 wifi_reloadAp(apIndex);
6451 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6452
6453 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006454}
6455
developer6daeb3f2022-09-30 13:36:39 +08006456// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006457INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6458{
developerd946fd62022-12-08 18:03:28 +08006459 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006460 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6461 char cmd[128] = {0};
6462 char buf[128] = {0};
6463 char ack_filepath[128] = {0};
6464 uint16_t bitmap = 0;
6465 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6466 FILE *f = NULL;
6467
6468 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6469
6470 // Get current setting
6471 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6472 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6473 _syscmd(cmd, buf, sizeof(buf));
6474 if (strlen(buf) > 0)
6475 bitmap = strtoul(buf, NULL, 10);
6476
6477 bitmap = strtoul(buf, NULL, 10);
6478
6479 if (ackPolicy == TRUE) { // True, unset this class
6480 bitmap &= ~class_map[class];
6481 } else { // False, set this class
6482 bitmap |= class_map[class];
6483 }
6484
6485 f = fopen(ack_filepath, "w");
6486 if (f == NULL) {
6487 fprintf(stderr, "%s: fopen failed\n", __func__);
6488 return RETURN_ERR;
6489 }
6490 fprintf(f, "%hu", bitmap);
6491 fclose(f);
6492
developerac6f1142022-12-20 19:26:35 +08006493 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006494 return RETURN_ERR;
6495 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006496 _syscmd(cmd, buf, sizeof(buf));
6497
6498 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6499 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006500}
6501
6502//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.
6503INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6504{
6505 //get the running status from driver
6506 if(!output_uint)
6507 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006508
6509 char output[16]={'\0'};
6510 char config_file[MAX_BUF_SIZE] = {0};
6511
6512 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6513 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6514 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6515 else {
6516 int device_num = atoi(output);
6517 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6518 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6519 return RETURN_ERR;
6520 }
6521 else {
6522 *output_uint = device_num;
6523 }
6524 }
6525
developer06a01d92022-09-07 16:32:39 +08006526 return RETURN_OK;
6527}
6528
6529INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6530{
6531 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006532 char str[MAX_BUF_SIZE]={'\0'};
6533 char cmd[MAX_CMD_SIZE]={'\0'};
6534 struct params params;
6535 char config_file[MAX_BUF_SIZE] = {0};
6536
6537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006538 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006539 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006540 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006541 }
6542 sprintf(str, "%d", number);
6543 params.name = "max_num_sta";
6544 params.value = str;
6545
6546 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6547 int ret = wifi_hostapdWrite(config_file, &params, 1);
6548 if (ret) {
6549 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6550 ,__func__, ret);
6551 }
6552
6553 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6554 if (ret) {
6555 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6556 ,__func__, ret);
6557 }
6558 wifi_reloadAp(apIndex);
6559 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6560
6561 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006562}
6563
6564//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.
6565INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6566{
6567 //get the current threshold
6568 if(!output_uint)
6569 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006570 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6571 if (*output_uint == 0)
6572 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006573 return RETURN_OK;
6574}
6575
6576INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6577{
6578 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006579 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6580 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006581 return RETURN_ERR;
6582}
6583
6584//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.
6585INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6586{
6587 if(!output_uint)
6588 return RETURN_ERR;
6589 *output_uint = 3;
6590 return RETURN_OK;
6591}
6592
6593//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6594INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6595{
6596 if(!output_uint)
6597 return RETURN_ERR;
6598 *output_uint = 3;
6599 return RETURN_OK;
6600}
6601
6602//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.
6603INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6604{
6605 if(!output_in_seconds)
6606 return RETURN_ERR;
6607 *output_in_seconds = 0;
6608 return RETURN_OK;
6609}
6610
6611//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
6612INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6613{
6614 if(!output || apIndex>=MAX_APS)
6615 return RETURN_ERR;
6616 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006617 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006618 return RETURN_OK;
6619}
6620
6621//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6622INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6623{
developer587c1b62022-09-27 15:58:59 +08006624 char config_file[128] = {0};
6625 char wpa[16] = {0};
6626 char key_mgmt[64] = {0};
6627 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006628 if (!output)
6629 return RETURN_ERR;
6630
6631 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006632 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006633
developer587c1b62022-09-27 15:58:59 +08006634 strcpy(output, "None");//Copying "None" to output string for default case
6635 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006636 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006637 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006638 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006639 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006640 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006641 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006642 snprintf(output, 32, "WPA-WPA2-Personal");
6643
developer72ec5572023-01-05 16:27:13 +08006644 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6645 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006646 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006647 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006648 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006649 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006650 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006651 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006652 snprintf(output, 32, "WPA-WPA2-Enterprise");
6653 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006654 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006655 snprintf(output, 32, "WPA3-Personal");
6656 else
developer4a359672022-10-13 15:30:46 +08006657 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006658 }
developer06a01d92022-09-07 16:32:39 +08006659
6660 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6661 return RETURN_OK;
6662#if 0
6663 //TODO: need to revisit below implementation
6664 char securityType[32], authMode[32];
6665 int enterpriseMode=0;
6666
6667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6668 if(!output)
6669 return RETURN_ERR;
6670
6671 wifi_getApBeaconType(apIndex, securityType);
6672 strcpy(output,"None");//By default, copying "None" to output string
6673 if (strncmp(securityType,"None", strlen("None")) == 0)
6674 return RETURN_OK;
6675
6676 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6677 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6678
6679 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6680 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6681 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6682 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6683 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6684 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6685 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6686
6687 return RETURN_OK;
6688#endif
6689}
6690
6691INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6692{
6693 char securityType[32];
6694 char authMode[32];
6695
6696 //store settings and wait for wifi up to apply
6697 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6698 if(!encMode)
6699 return RETURN_ERR;
6700
developer06a01d92022-09-07 16:32:39 +08006701 if (strcmp(encMode, "None")==0)
6702 {
6703 strcpy(securityType,"None");
6704 strcpy(authMode,"None");
6705 }
6706 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6707 {
6708 strcpy(securityType,"WPAand11i");
6709 strcpy(authMode,"PSKAuthentication");
6710 }
6711 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6712 {
6713 strcpy(securityType,"WPAand11i");
6714 strcpy(authMode,"EAPAuthentication");
6715 }
6716 else if (strcmp(encMode, "WPA-Personal")==0)
6717 {
6718 strcpy(securityType,"WPA");
6719 strcpy(authMode,"PSKAuthentication");
6720 }
6721 else if (strcmp(encMode, "WPA-Enterprise")==0)
6722 {
6723 strcpy(securityType,"WPA");
6724 strcpy(authMode,"EAPAuthentication");
6725 }
6726 else if (strcmp(encMode, "WPA2-Personal")==0)
6727 {
6728 strcpy(securityType,"11i");
6729 strcpy(authMode,"PSKAuthentication");
6730 }
6731 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6732 {
6733 strcpy(securityType,"11i");
6734 strcpy(authMode,"EAPAuthentication");
6735 }
developer587c1b62022-09-27 15:58:59 +08006736 else if (strcmp(encMode, "WPA3-Personal") == 0)
6737 {
6738 strcpy(securityType,"11i");
6739 strcpy(authMode,"SAEAuthentication");
6740 }
developer4a359672022-10-13 15:30:46 +08006741 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006742 {
6743 strcpy(securityType, "11i");
6744 strcpy(authMode, "PSK-SAEAuthentication");
6745 }
developer587c1b62022-09-27 15:58:59 +08006746 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6747 {
6748 strcpy(securityType,"11i");
6749 strcpy(authMode,"EAP_192-bit_Authentication");
6750 }
developer5c9fee82023-01-13 14:44:16 +08006751 else if (strcmp(encMode, "OWE") == 0)
6752 {
6753 strcpy(securityType,"11i");
6754 strcpy(authMode,"Enhanced_Open");
6755 }
developer06a01d92022-09-07 16:32:39 +08006756 else
6757 {
6758 strcpy(securityType,"None");
6759 strcpy(authMode,"None");
6760 }
6761 wifi_setApBeaconType(apIndex, securityType);
6762 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6763 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6764
6765 return RETURN_OK;
6766}
6767
6768
developer4b102122023-02-15 10:53:03 +08006769// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006770//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006771INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6772{
developer30423732022-12-01 16:17:49 +08006773 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006774 char config_file[MAX_BUF_SIZE] = {0};
6775
6776 if(output_string==NULL)
6777 return RETURN_ERR;
6778
6779 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6780 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6781
6782 if(strcmp(buf,"0")==0)
6783 {
6784 printf("wpa_mode is %s ......... \n",buf);
6785 return RETURN_ERR;
6786 }
6787
6788 wifi_dbg_printf("\nFunc=%s\n",__func__);
6789 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006790 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006791 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6792
6793 return RETURN_OK;
6794}
6795
developer4b102122023-02-15 10:53:03 +08006796// Set PreSharedKey associated with a Access Point.
6797// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006798INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6799{
6800 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6801 struct params params={'\0'};
6802 int ret;
6803 char config_file[MAX_BUF_SIZE] = {0};
6804
6805 if(NULL == preSharedKey)
6806 return RETURN_ERR;
6807
developer4b102122023-02-15 10:53:03 +08006808 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006809
developer4b102122023-02-15 10:53:03 +08006810 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006811 {
developer4b102122023-02-15 10:53:03 +08006812 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006813 return RETURN_ERR;
6814 }
6815 params.value = preSharedKey;
6816 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6817 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006818 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006819 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006820 wifi_reloadAp(apIndex);
6821 }
developer06a01d92022-09-07 16:32:39 +08006822 return ret;
6823 //TODO: call hostapd_cli for dynamic_config_control
6824}
6825
6826//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6827// outputs the passphrase, maximum 63 characters
6828INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6829{
6830 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6831
6832 wifi_dbg_printf("\nFunc=%s\n",__func__);
6833 if (NULL == output_string)
6834 return RETURN_ERR;
6835
6836 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6837 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6838 if(strcmp(buf,"0")==0)
6839 {
6840 printf("wpa_mode is %s ......... \n",buf);
6841 return RETURN_ERR;
6842 }
6843
6844 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6845 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6846
6847 return RETURN_OK;
6848}
6849
6850// sets the passphrase enviornment variable, max 63 characters
6851INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6852{
6853 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6854 struct params params={'\0'};
6855 char config_file[MAX_BUF_SIZE] = {0};
6856 int ret;
6857
6858 if(NULL == passPhrase)
6859 return RETURN_ERR;
6860
6861 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6862 {
6863 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6864 return RETURN_ERR;
6865 }
6866 params.name = "wpa_passphrase";
6867 params.value = passPhrase;
6868 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6869 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006870 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006871 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006872 wifi_reloadAp(apIndex);
6873 }
developer06a01d92022-09-07 16:32:39 +08006874
6875 return ret;
6876}
6877
6878//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.
6879INT wifi_setApSecurityReset(INT apIndex)
6880{
developer8d583982022-09-20 11:28:22 +08006881 char original_config_file[64] = {0};
6882 char current_config_file[64] = {0};
6883 char buf[64] = {0};
6884 char cmd[64] = {0};
6885 char wpa[4] = {0};
6886 char wpa_psk[64] = {0};
6887 char wpa_passphrase[64] = {0};
6888 char wpa_psk_file[128] = {0};
6889 char wpa_key_mgmt[64] = {0};
6890 char wpa_pairwise[32] = {0};
6891 wifi_band band;
6892 struct params list[6];
6893
6894 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6895
6896 band = wifi_index_to_band(apIndex);
6897 if (band == band_2_4)
6898 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006899 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006900 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006901 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006902 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6903 else
6904 return RETURN_ERR;
6905
6906 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6907 list[0].name = "wpa";
6908 list[0].value = wpa;
6909
6910 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6911 list[1].name = "wpa_psk";
6912 list[1].value = wpa_psk;
6913
6914 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6915 list[2].name = "wpa_passphrase";
6916 list[2].value = wpa_passphrase;
6917
6918 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6919
6920 if (strlen(wpa_psk_file) == 0)
6921 strcpy(wpa_psk_file, PSK_FILE);
6922
6923 if (access(wpa_psk_file, F_OK) != 0) {
6924 sprintf(cmd, "touch %s", wpa_psk_file);
6925 _syscmd(cmd, buf, sizeof(buf));
6926 }
6927 list[3].name = "wpa_psk_file";
6928 list[3].value = wpa_psk_file;
6929
6930 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6931 list[4].name = "wpa_key_mgmt";
6932 list[4].value = wpa_key_mgmt;
6933
6934 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6935 list[5].name = "wpa_pairwise";
6936 list[5].value = wpa_pairwise;
6937
6938 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6939 wifi_hostapdWrite(current_config_file, list, 6);
6940
6941 wifi_setApEnable(apIndex, FALSE);
6942 wifi_setApEnable(apIndex, TRUE);
6943
6944 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6945 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006946}
6947
6948//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).
6949INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6950{
developer8f2ddd52022-09-13 15:39:24 +08006951 char config_file[64] = {0};
6952 char buf[64] = {0};
6953 char cmd[256] = {0};
6954
6955 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6956
developer06a01d92022-09-07 16:32:39 +08006957 if(!IP_output || !Port_output || !RadiusSecret_output)
6958 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006959
developer8f2ddd52022-09-13 15:39:24 +08006960 // Read the first matched config
6961 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6962 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6963 _syscmd(cmd, buf, sizeof(buf));
6964 strncpy(IP_output, buf, 64);
6965
6966 memset(buf, 0, sizeof(buf));
6967 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6968 _syscmd(cmd, buf, sizeof(buf));
6969 *Port_output = atoi(buf);
6970
6971 memset(buf, 0, sizeof(buf));
6972 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6973 _syscmd(cmd, buf, sizeof(buf));
6974 strncpy(RadiusSecret_output, buf, 64);
6975
6976 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006977 return RETURN_OK;
6978}
6979
6980INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6981{
developer8f2ddd52022-09-13 15:39:24 +08006982 char config_file[64] = {0};
6983 char port_str[8] = {0};
6984 char cmd[256] = {0};
6985 char buf[128] = {0};
6986
6987 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08006988 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
6989 return RETURN_ERR;
6990
6991 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
6992 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006993
6994 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6995
6996 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6997 _syscmd(cmd, buf, sizeof(buf));
6998 memset(cmd, 0, sizeof(cmd));
6999
7000 snprintf(port_str, sizeof(port_str), "%d", port);
7001 if (strlen(buf) == 0)
7002 // Append
7003 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7004 "auth_server_addr=%s\\n"
7005 "auth_server_port=%s\\n"
7006 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7007 else {
7008 // Delete the three lines setting after the "# radius 1" comment
7009 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7010 _syscmd(cmd, buf, sizeof(buf));
7011 memset(cmd, 0, sizeof(cmd));
7012 // Use "# radius 1" comment to find the location to insert the radius setting
7013 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7014 "# radius 1\\n"
7015 "auth_server_addr=%s\\n"
7016 "auth_server_port=%s\\n"
7017 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7018 }
7019 if(_syscmd(cmd, buf, sizeof(buf))) {
7020 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7021 return RETURN_ERR;
7022 }
7023
7024 wifi_reloadAp(apIndex);
7025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7026 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007027}
7028
7029INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7030{
developer8f2ddd52022-09-13 15:39:24 +08007031 char config_file[64] = {0};
7032 char buf[64] = {0};
7033 char cmd[256] = {0};
7034
7035 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7036
developer06a01d92022-09-07 16:32:39 +08007037 if(!IP_output || !Port_output || !RadiusSecret_output)
7038 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007039
7040 // Read the second matched config
7041 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7042 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7043 _syscmd(cmd, buf, sizeof(buf));
7044 strncpy(IP_output, buf, 64);
7045
7046 memset(buf, 0, sizeof(buf));
7047 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7048 _syscmd(cmd, buf, sizeof(buf));
7049 *Port_output = atoi(buf);
7050
7051 memset(buf, 0, sizeof(buf));
7052 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7053 _syscmd(cmd, buf, sizeof(buf));
7054 strncpy(RadiusSecret_output, buf, 64);
7055
7056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007057 return RETURN_OK;
7058}
7059
7060INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7061{
developer8f2ddd52022-09-13 15:39:24 +08007062 char config_file[64] = {0};
7063 char port_str[8] = {0};
7064 char cmd[256] = {0};
7065 char buf[128] = {0};
7066
7067 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007068 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7069 return RETURN_ERR;
7070
7071 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7072 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007073
7074 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7075
7076 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7077 _syscmd(cmd, buf, sizeof(buf));
7078 memset(cmd, 0, sizeof(cmd));
7079
7080 snprintf(port_str, sizeof(port_str), "%d", port);
7081 if (strlen(buf) == 0)
7082 // Append
7083 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7084 "auth_server_addr=%s\\n"
7085 "auth_server_port=%s\\n"
7086 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7087 else {
7088 // Delete the three lines setting after the "# radius 2" comment
7089 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7090 _syscmd(cmd, buf, sizeof(buf));
7091 memset(cmd, 0, sizeof(cmd));
7092 // Use "# radius 2" comment to find the location to insert the radius setting
7093 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7094 "# radius 2\\n"
7095 "auth_server_addr=%s\\n"
7096 "auth_server_port=%s\\n"
7097 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7098 }
7099 if(_syscmd(cmd, buf, sizeof(buf))) {
7100 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7101 return RETURN_ERR;
7102 }
7103
7104 wifi_reloadAp(apIndex);
7105 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7106 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007107}
7108
7109//RadiusSettings
7110INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7111{
7112 if(!output)
7113 return RETURN_ERR;
7114
7115 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7116 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7117 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7118 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7119 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7120 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.
7121 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7122 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7123 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7124 //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.
7125
7126 return RETURN_OK;
7127}
7128
7129INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7130{
7131 //store the paramters, and apply instantly
7132 return RETURN_ERR;
7133}
7134
7135//Device.WiFi.AccessPoint.{i}.WPS.Enable
7136//Enables or disables WPS functionality for this access point.
7137// outputs the WPS enable state of this ap in output_bool
7138INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7139{
developerd946fd62022-12-08 18:03:28 +08007140 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007141 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer613892e2023-09-21 16:33:35 +08007142
7143 *output_bool=FALSE;
developer5b398df2022-11-17 20:39:48 +08007144 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007145 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007146 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer613892e2023-09-21 16:33:35 +08007147 return RETURN_OK;
developerd946fd62022-12-08 18:03:28 +08007148 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007149 _syscmd(cmd, buf, sizeof(buf));
7150 if(strstr(buf, "configured"))
7151 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08007152
7153 return RETURN_OK;
developer613892e2023-09-21 16:33:35 +08007154}
developer06a01d92022-09-07 16:32:39 +08007155
7156//Device.WiFi.AccessPoint.{i}.WPS.Enable
7157// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7158INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7159{
7160 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007161 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007162 struct params params;
7163
developer06a01d92022-09-07 16:32:39 +08007164 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7165 //store the paramters, and wait for wifi up to apply
7166 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007167 if (enable == TRUE) {
7168 wifi_getApBeaconType(apIndex, buf);
7169 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7170 params.value = "1";
7171 else // If ap set encryption
7172 params.value = "2";
7173 } else {
7174 params.value = "0";
7175 }
developer06a01d92022-09-07 16:32:39 +08007176
7177 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7178 wifi_hostapdWrite(config_file, &params, 1);
7179 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7180 wifi_reloadAp(apIndex);
7181
7182 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7183 return RETURN_OK;
7184}
7185
7186//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
7187INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7188{
7189 if(!output)
7190 return RETURN_ERR;
7191 snprintf(output, 128, "PushButton,PIN");
7192 return RETURN_OK;
7193}
7194
7195//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7196//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.
7197// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7198INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7199{
7200 if(!output)
7201 return RETURN_ERR;
7202 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7203
7204 return RETURN_OK;
7205}
7206
7207//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7208// 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
7209INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7210{
7211 //apply instantly. No setting need to be stored.
7212 char methods[MAX_BUF_SIZE], *token, *next_token;
7213 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7214 struct params params;
7215
developer5b398df2022-11-17 20:39:48 +08007216 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007217 return RETURN_ERR;
7218 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7219 //store the paramters, and wait for wifi up to apply
7220
7221 snprintf(methods, sizeof(methods), "%s", methodString);
7222 for(token=methods; *token; token=next_token)
7223 {
7224 strtok_r(token, ",", &next_token);
7225 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7226 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7227 else if(*token=='E')
7228 {
7229 if(!strcmp(methods, "Ethernet"))
7230 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7231 else if(!strcmp(methods, "ExternalNFCToken"))
7232 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7233 else
7234 printf("%s: Unknown WpsConfigMethod\n", __func__);
7235 }
7236 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7237 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7238 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7239 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7240 else if(*token=='P' )
7241 {
7242 if(!strcmp(token, "PushButton"))
developer894affa2023-05-10 18:13:19 +08007243 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer06a01d92022-09-07 16:32:39 +08007244 else if(!strcmp(token, "PIN"))
7245 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7246 else
7247 printf("%s: Unknown WpsConfigMethod\n", __func__);
7248 }
7249 else
7250 printf("%s: Unknown WpsConfigMethod\n", __func__);
7251 }
7252 params.name = "config_methods";
7253 params.value = config_methods;
7254 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7255 wifi_hostapdWrite(config_file, &params, 1);
7256 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7257 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7258
7259 return RETURN_OK;
7260}
7261
7262// outputs the pin value, ulong_pin must be allocated by the caller
7263INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7264{
7265 char buf[MAX_BUF_SIZE] = {0};
7266 char cmd[MAX_CMD_SIZE] = {0};
7267
developer5b398df2022-11-17 20:39:48 +08007268 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007269 return RETURN_ERR;
7270 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7271 _syscmd(cmd, buf, sizeof(buf));
7272 if(strlen(buf) > 0)
7273 *output_ulong=strtoul(buf, NULL, 10);
7274
7275 return RETURN_OK;
7276}
7277
7278// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7279INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7280{
7281 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7282 char ap_pin[16] = {0};
7283 char buf[MAX_BUF_SIZE] = {0};
7284 char config_file[MAX_BUF_SIZE] = {0};
7285 ULONG prev_pin = 0;
7286 struct params params;
7287
developer06a01d92022-09-07 16:32:39 +08007288 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7289 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7290 params.name = "ap_pin";
7291 params.value = ap_pin;
7292 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7293 wifi_hostapdWrite(config_file, &params, 1);
7294 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7295 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7296
7297 return RETURN_OK;
7298}
7299
7300// Output string is either Not configured or Configured, max 32 characters
7301INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7302{
developerd946fd62022-12-08 18:03:28 +08007303 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007304 char cmd[MAX_CMD_SIZE];
7305 char buf[MAX_BUF_SIZE]={0};
7306
developer5b398df2022-11-17 20:39:48 +08007307 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007308 return RETURN_ERR;
7309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7310 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007311 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007312 return RETURN_ERR;
7313 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007314 _syscmd(cmd, buf, sizeof(buf));
7315
developer348e3d92022-09-13 14:48:41 +08007316 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007317 snprintf(output_string, 32, "Configured");
7318 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7319
7320 return RETURN_OK;
7321}
7322
7323// sets the WPS pin for this AP
7324INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7325{
developerd946fd62022-12-08 18:03:28 +08007326 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007327 char cmd[MAX_CMD_SIZE];
7328 char buf[MAX_BUF_SIZE]={0};
7329 BOOL enable;
7330
developer06a01d92022-09-07 16:32:39 +08007331 wifi_getApEnable(apIndex, &enable);
7332 if (!enable)
7333 return RETURN_ERR;
7334 wifi_getApWpsEnable(apIndex, &enable);
7335 if (!enable)
7336 return RETURN_ERR;
7337
developerac6f1142022-12-20 19:26:35 +08007338 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007339 return RETURN_ERR;
7340 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007341 _syscmd(cmd, buf, sizeof(buf));
7342 if((strstr(buf, "OK"))!=NULL)
7343 return RETURN_OK;
7344
7345 return RETURN_ERR;
7346}
7347
7348// This function is called when the WPS push button has been pressed for this AP
7349INT wifi_setApWpsButtonPush(INT apIndex)
7350{
7351 char cmd[MAX_CMD_SIZE];
7352 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007353 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007354 BOOL enable=FALSE;
7355
developer06a01d92022-09-07 16:32:39 +08007356 wifi_getApEnable(apIndex, &enable);
7357 if (!enable)
7358 return RETURN_ERR;
7359
7360 wifi_getApWpsEnable(apIndex, &enable);
7361 if (!enable)
7362 return RETURN_ERR;
7363
developerac6f1142022-12-20 19:26:35 +08007364 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007365 return RETURN_ERR;
7366
developer900e2b72023-05-23 10:23:48 +08007367 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 +08007368 _syscmd(cmd, buf, sizeof(buf));
7369
7370 if((strstr(buf, "OK"))!=NULL)
7371 return RETURN_OK;
7372 return RETURN_ERR;
7373}
7374
7375// cancels WPS mode for this AP
7376INT wifi_cancelApWPS(INT apIndex)
7377{
developerd946fd62022-12-08 18:03:28 +08007378 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007379 char cmd[MAX_CMD_SIZE];
7380 char buf[MAX_BUF_SIZE]={0};
7381
developerac6f1142022-12-20 19:26:35 +08007382 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007383 return RETURN_ERR;
7384 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007385 _syscmd(cmd,buf, sizeof(buf));
7386
7387 if((strstr(buf, "OK"))!=NULL)
7388 return RETURN_OK;
7389 return RETURN_ERR;
7390}
7391
7392//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7393//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7394INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7395{
developerd946fd62022-12-08 18:03:28 +08007396 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007397 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007398 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007399 char cmd[256] = {0}, buf[2048] = {0};
7400 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007401 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007402 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007403 wifi_associated_dev_t *dev=NULL;
7404
7405 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7406 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007407 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007408 return RETURN_ERR;
7409 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007410 _syscmd(cmd,buf,sizeof(buf));
7411 *output_array_size = atoi(buf);
7412
7413 if (*output_array_size <= 0)
7414 return RETURN_OK;
7415
7416 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7417 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007418 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007419 _syscmd(cmd,buf,sizeof(buf));
7420 f = fopen("/tmp/connected_devices.txt", "r");
7421 if (f==NULL)
7422 {
7423 *output_array_size=0;
7424 return RETURN_ERR;
7425 }
developer30423732022-12-01 16:17:49 +08007426 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007427 {
7428 param = strtok(line,"=");
7429 value = strtok(NULL,"=");
7430
7431 if( strcmp("flags",param) == 0 )
7432 {
7433 value[strlen(value)-1]='\0';
7434 if(strstr (value,"AUTHORIZED") != NULL )
7435 {
7436 dev[auth_temp].cli_AuthenticationState = 1;
7437 dev[auth_temp].cli_Active = 1;
7438 auth_temp++;
7439 read_flag=1;
7440 }
7441 }
7442 if(read_flag==1)
7443 {
7444 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7445 {
7446 value[strlen(value)-1]='\0';
7447 sscanf(value, "%x:%x:%x:%x:%x:%x",
7448 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7449 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7450 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7451 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7452 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7453 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7454 mac_temp++;
7455 read_flag=0;
7456 }
7457 }
7458 }
7459 *output_array_size = auth_temp;
7460 auth_temp=0;
7461 mac_temp=0;
7462 free(line);
7463 fclose(f);
7464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7465 return RETURN_OK;
7466}
7467
7468#define MACADDRESS_SIZE 6
7469
7470INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7471{
7472 FILE *fp = NULL;
7473 char str[MAX_BUF_SIZE] = {0};
7474 int wificlientindex = 0 ;
7475 int count = 0;
7476 int signalstrength = 0;
7477 int arr[MACADDRESS_SIZE] = {0};
7478 unsigned char mac[MACADDRESS_SIZE] = {0};
7479 UINT wifi_count = 0;
7480 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7481 char pipeCmd[MAX_CMD_SIZE] = {0};
7482
7483 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7484 *output_array_size = 0;
7485 *associated_dev_array = NULL;
7486
7487 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7488 fp = popen(pipeCmd, "r");
7489 if (fp == NULL)
7490 {
7491 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7492 return RETURN_ERR;
7493 }
7494
7495 /* Read the output a line at a time - output it. */
7496 fgets(str, sizeof(str)-1, fp);
7497 wifi_count = (unsigned int) atoi ( str );
7498 *output_array_size = wifi_count;
7499 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7500 pclose(fp);
7501
7502 if(wifi_count == 0)
7503 {
7504 return RETURN_OK;
7505 }
7506 else
7507 {
7508 wifi_associated_dev3_t* temp = NULL;
7509 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7510 if(temp == NULL)
7511 {
7512 printf("Error Statement. Insufficient memory \n");
7513 return RETURN_ERR;
7514 }
7515
7516 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7517 system(pipeCmd);
7518 memset(pipeCmd,0,sizeof(pipeCmd));
7519 if(apIndex == 0)
7520 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7521 else if(apIndex == 1)
7522 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7523 system(pipeCmd);
7524
7525 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7526 if(fp == NULL)
7527 {
7528 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007529 free(temp);
developer06a01d92022-09-07 16:32:39 +08007530 return RETURN_ERR;
7531 }
7532 fclose(fp);
7533
developer30423732022-12-01 16:17:49 +08007534 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007535 fp = popen(pipeCmd, "r");
7536 if(fp)
7537 {
7538 for(count =0 ; count < wifi_count; count++)
7539 {
7540 fgets(str, MAX_BUF_SIZE, fp);
7541 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7542 {
7543 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7544 {
7545 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7546
7547 }
7548 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7549 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]);
7550 }
7551 temp[count].cli_AuthenticationState = 1; //TODO
7552 temp[count].cli_Active = 1; //TODO
7553 }
7554 pclose(fp);
7555 }
7556
developer30423732022-12-01 16:17:49 +08007557 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 +08007558 fp = popen(pipeCmd, "r");
7559 if(fp)
7560 {
7561 pclose(fp);
7562 }
7563 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7564 if(fp)
7565 {
7566 for(count =0 ; count < wifi_count ;count++)
7567 {
7568 fgets(str, MAX_BUF_SIZE, fp);
7569 signalstrength = atoi(str);
7570 temp[count].cli_SignalStrength = signalstrength;
7571 temp[count].cli_RSSI = signalstrength;
7572 temp[count].cli_SNR = signalstrength + 95;
7573 }
7574 pclose(fp);
7575 }
7576
7577
7578 if((apIndex == 0) || (apIndex == 4))
7579 {
7580 for(count =0 ; count < wifi_count ;count++)
7581 {
7582 strcpy(temp[count].cli_OperatingStandard,"g");
7583 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7584 }
7585
7586 //BytesSent
developer30423732022-12-01 16:17:49 +08007587 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 +08007588 fp = popen(pipeCmd, "r");
7589 if(fp)
7590 {
7591 pclose(fp);
7592 }
7593 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7594 if(fp)
7595 {
7596 for (count = 0; count < wifi_count; count++)
7597 {
7598 fgets(str, MAX_BUF_SIZE, fp);
7599 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7600 }
7601 pclose(fp);
7602 }
7603
7604 //BytesReceived
developer30423732022-12-01 16:17:49 +08007605 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 +08007606 fp = popen(pipeCmd, "r");
7607 if (fp)
7608 {
7609 pclose(fp);
7610 }
7611 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7612 if (fp)
7613 {
7614 for (count = 0; count < wifi_count; count++)
7615 {
7616 fgets(str, MAX_BUF_SIZE, fp);
7617 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7618 }
7619 pclose(fp);
7620 }
7621
7622 //PacketsSent
developer30423732022-12-01 16:17:49 +08007623 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 +08007624 fp = popen(pipeCmd, "r");
7625 if (fp)
7626 {
7627 pclose(fp);
7628 }
7629
7630 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7631 if (fp)
7632 {
7633 for (count = 0; count < wifi_count; count++)
7634 {
7635 fgets(str, MAX_BUF_SIZE, fp);
7636 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7637 }
7638 pclose(fp);
7639 }
7640
7641 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007642 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 +08007643 fp = popen(pipeCmd, "r");
7644 if (fp)
7645 {
7646 pclose(fp);
7647 }
7648 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7649 if (fp)
7650 {
7651 for (count = 0; count < wifi_count; count++)
7652 {
7653 fgets(str, MAX_BUF_SIZE, fp);
7654 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7655 }
7656 pclose(fp);
7657 }
7658
7659 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007660 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 +08007661 fp = popen(pipeCmd, "r");
7662 if (fp)
7663 {
7664 pclose(fp);
7665 }
7666 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7667 if (fp)
7668 {
7669 for (count = 0; count < wifi_count; count++)
7670 {
7671 fgets(str, MAX_BUF_SIZE, fp);
7672 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7673 }
7674 pclose(fp);
7675 }
7676
7677 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007678 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 +08007679 fp = popen(pipeCmd, "r");
7680 if (fp)
7681 {
7682 pclose(fp);
7683 }
7684 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7685 if (fp)
7686 {
7687 for (count = 0; count < wifi_count; count++)
7688 {
7689 fgets(str, MAX_BUF_SIZE, fp);
7690 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7691 }
7692 pclose(fp);
7693 }
7694
7695 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007696 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 +08007697 fp = popen(pipeCmd, "r");
7698 if (fp)
7699 {
7700 pclose(fp);
7701 }
7702 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7703 if (fp)
7704 {
7705 for (count = 0; count < wifi_count; count++)
7706 {
7707 fgets(str, MAX_BUF_SIZE, fp);
7708 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7709 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7710 }
7711 pclose(fp);
7712 }
7713
7714 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007715 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 +08007716 fp = popen(pipeCmd, "r");
7717 if (fp)
7718 {
7719 pclose(fp);
7720 }
7721 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7722 if (fp)
7723 {
7724 for (count = 0; count < wifi_count; count++)
7725 {
7726 fgets(str, MAX_BUF_SIZE, fp);
7727 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7728 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7729 }
7730 pclose(fp);
7731 }
7732
7733 }
7734 else if ((apIndex == 1) || (apIndex == 5))
7735 {
7736 for (count = 0; count < wifi_count; count++)
7737 {
7738 strcpy(temp[count].cli_OperatingStandard, "a");
7739 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7740 temp[count].cli_BytesSent = 0;
7741 temp[count].cli_BytesReceived = 0;
7742 temp[count].cli_LastDataUplinkRate = 0;
7743 temp[count].cli_LastDataDownlinkRate = 0;
7744 temp[count].cli_PacketsSent = 0;
7745 temp[count].cli_PacketsReceived = 0;
7746 temp[count].cli_ErrorsSent = 0;
7747 }
7748 }
7749
7750 for (count = 0; count < wifi_count; count++)
7751 {
7752 temp[count].cli_Retransmissions = 0;
7753 temp[count].cli_DataFramesSentAck = 0;
7754 temp[count].cli_DataFramesSentNoAck = 0;
7755 temp[count].cli_MinRSSI = 0;
7756 temp[count].cli_MaxRSSI = 0;
7757 strncpy(temp[count].cli_InterferenceSources, "", 64);
7758 memset(temp[count].cli_IPAddress, 0, 64);
7759 temp[count].cli_RetransCount = 0;
7760 temp[count].cli_FailedRetransCount = 0;
7761 temp[count].cli_RetryCount = 0;
7762 temp[count].cli_MultipleRetryCount = 0;
7763 }
7764 *associated_dev_array = temp;
7765 }
7766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7767 return RETURN_OK;
7768}
7769
7770int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7771{
7772 FILE *fp = NULL;
7773 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7774 char cmd[MAX_CMD_SIZE];
7775 int count = 0;
7776
7777 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7778 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7779 fp = popen(cmd,"r");
7780 if(fp == NULL)
7781 {
7782 printf("Failed to run command in Function %s\n",__FUNCTION__);
7783 return 0;
7784 }
7785 if(fgets(path, sizeof(path)-1, fp) != NULL)
7786 {
7787 for(count=0;path[count]!='\n';count++)
7788 status[count]=path[count];
7789 status[count]='\0';
7790 }
7791 strcpy(wifi_status,status);
7792 pclose(fp);
7793 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7794 return RETURN_OK;
7795}
7796
7797/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7798struct hostapd_sta_param {
7799 char key[50];
7800 char value[100];
7801}
7802
7803static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7804 int i = 0;
7805
7806 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7807 if (strncmp(params[i].key,key,50) == 0){
7808 return &params[i].value;
7809 }
7810 i++;
7811 }
7812 return NULL;
7813
7814} */
7815
7816static unsigned int count_occurences(const char *buf, const char *word)
7817{
7818 unsigned int n = 0;
7819 char *ptr = strstr(buf, word);
7820
7821 while (ptr++) {
7822 n++;
7823 ptr = strstr(ptr, word);
7824 }
7825
7826 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7827 return n;
7828}
7829
7830static const char *get_line_from_str_buf(const char *buf, char *line)
7831{
7832 int i;
7833 int n = strlen(buf);
7834
7835 for (i = 0; i < n; i++) {
7836 line[i] = buf[i];
7837 if (buf[i] == '\n') {
7838 line[i] = '\0';
7839 return &buf[i + 1];
7840 }
7841 }
7842
7843 return NULL;
7844}
7845
developer9a9f46e2023-11-09 09:22:42 +08007846static INT wifi_getAssocConnectMode(INT apIndex, CHAR *input_string, CHAR *OperatingStandard)
7847{
7848 wifi_band band;
7849 int ieee80211_mode = 0;
7850
7851 if (!input_string || !OperatingStandard)
7852 return RETURN_ERR;
7853
7854 band = wifi_index_to_band(apIndex);
7855
7856 if (strstr(input_string, "HE"))
7857 ieee80211_mode = WIFI_MODE_AX;
7858 else if (strstr(input_string, "VHT"))
7859 ieee80211_mode = WIFI_MODE_AC;
7860 else if (strstr(input_string, "EHT"))
7861 ieee80211_mode = WIFI_MODE_BE;
7862
7863 switch (ieee80211_mode) {
7864 case WIFI_MODE_AC:
7865 strncpy(OperatingStandard, "ac", 2);
7866 break;
7867 case WIFI_MODE_AX:
7868 strncpy(OperatingStandard, "ax", 2);
7869 break;
7870 case WIFI_MODE_BE:
7871 strncpy(OperatingStandard, "be", 2);
7872 break;
7873 default:
7874 if(band == band_2_4)
7875 strncpy(OperatingStandard,"b,g,n", 5);
7876 else if(band == band_5)
7877 strncpy(OperatingStandard,"a,n", 3);
7878 else if(band == band_6)
7879 strncpy(OperatingStandard,"ax", 2);
7880 else {
7881 wifi_dbg_printf("%s: failed to parse band %d\n", __FUNCTION__, band);
7882 return RETURN_ERR;
7883 }
7884 }
7885
7886
7887 return RETURN_OK;
7888}
7889
developer06a01d92022-09-07 16:32:39 +08007890INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7891{
7892 unsigned int assoc_cnt = 0;
7893 char interface_name[50] = {0};
7894 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7895 char cmd[MAX_CMD_SIZE] = {'\0'};
7896 char line[256] = {'\0'};
7897 int i = 0;
7898 int ret = 0;
7899 const char *ptr = NULL;
7900 char *key = NULL;
7901 char *val = NULL;
7902 wifi_associated_dev3_t *temp = NULL;
7903 int rssi;
7904
7905 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7906
7907 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7908 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7909 return RETURN_ERR;
7910 }
7911
7912 // Example filtered output of 'iw dev' command:
7913 // Station 0a:69:72:10:d2:fa (on wifi0)
7914 // signal avg:-67 [-71, -71] dBm
7915 // Station 28:c2:1f:25:5f:99 (on wifi0)
7916 // signal avg:-67 [-71, -70] dBm
developer9a9f46e2023-11-09 09:22:42 +08007917 if (sprintf(cmd,"iw dev %s station dump | tr -d '\t' | grep -E 'Station|signal avg"
7918 "|tx bitrate|rx bitrate'", interface_name) < 0) {
7919 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
developer06a01d92022-09-07 16:32:39 +08007920 return RETURN_ERR;
7921 }
7922
7923 ret = _syscmd(cmd, buf, sizeof(buf));
7924 if (ret == RETURN_ERR) {
7925 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7926 return RETURN_ERR;
7927 }
7928
7929 *output_array_size = count_occurences(buf, "Station");
7930 if (*output_array_size == 0) return RETURN_OK;
7931
7932 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7933 if (temp == NULL) {
7934 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7935 return RETURN_ERR;
7936 }
7937 *associated_dev_array = temp;
7938
7939 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7940 ptr = get_line_from_str_buf(buf, line);
7941 i = -1;
7942 while (ptr) {
7943 if (strstr(line, "Station")) {
7944 i++;
7945 key = strtok(line, " ");
7946 val = strtok(NULL, " ");
7947 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7948 &temp[i].cli_MACAddress[0],
7949 &temp[i].cli_MACAddress[1],
7950 &temp[i].cli_MACAddress[2],
7951 &temp[i].cli_MACAddress[3],
7952 &temp[i].cli_MACAddress[4],
7953 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7954 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7955 free(*associated_dev_array);
7956 return RETURN_ERR;
7957 }
7958 }
7959 else if (i < 0) {
developer9a9f46e2023-11-09 09:22:42 +08007960 wifi_dbg_printf("%s: not find station\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +08007961 ptr = get_line_from_str_buf(ptr, line);
7962 continue; // We didn't detect 'station' entry yet
7963 }
7964 else if (strstr(line, "signal avg")) {
7965 key = strtok(line, ":");
7966 val = strtok(NULL, " ");
7967 if (sscanf(val, "%d", &rssi) <= 0 ) {
7968 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7969 free(*associated_dev_array);
7970 return RETURN_ERR;
7971 }
7972 temp[i].cli_RSSI = rssi;
7973 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7974 }
developer9a9f46e2023-11-09 09:22:42 +08007975 else if (strstr(line, "tx bitrate")) {
7976 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
7977 if (ret == RETURN_ERR) {
7978 wifi_dbg_printf("%s: failed to execute tx get assoc connect mode command.\n", __FUNCTION__);
7979 return ret;
7980 }
7981 }
7982 else if (strstr(line, "rx bitrate")) {
7983 /* if tx get ac, ax, be mode, need not get mode from rx */
7984 if (strncmp(temp[i].cli_OperatingStandard,"ac", 2) &&
7985 strncmp(temp[i].cli_OperatingStandard,"ax", 2) &&
7986 strncmp(temp[i].cli_OperatingStandard,"be", 2)) {
7987 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
7988 if (ret == RETURN_ERR) {
7989 wifi_dbg_printf("%s: failed to execute rx get assoc connect mode command.\n", __FUNCTION__);
7990 return ret;
7991 }
7992 }
7993 }
developer06a01d92022-09-07 16:32:39 +08007994 // Here other fields can be parsed if added to filter of 'iw dev' command
developer06a01d92022-09-07 16:32:39 +08007995 ptr = get_line_from_str_buf(ptr, line);
developer9a9f46e2023-11-09 09:22:42 +08007996 }
developer06a01d92022-09-07 16:32:39 +08007997
7998 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007999 return RETURN_OK;
8000}
8001
8002#if 0
8003//To-do
8004INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8005{
8006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8007
8008 //Using different approach to get required WiFi Parameters from system available commands
8009#if 0
8010 FILE *f;
8011 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8012 char cmd[256], buf[2048];
8013 char *param , *value, *line=NULL;
8014 size_t len = 0;
8015 ssize_t nread;
8016 wifi_associated_dev3_t *dev=NULL;
8017 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08008018 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08008019 _syscmd(cmd,buf,sizeof(buf));
8020 *output_array_size = atoi(buf);
8021
8022 if (*output_array_size <= 0)
8023 return RETURN_OK;
8024
8025 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8026 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08008027 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08008028 _syscmd(cmd,buf,sizeof(buf));
8029 f = fopen("/tmp/connected_devices.txt", "r");
8030 if (f==NULL)
8031 {
8032 *output_array_size=0;
8033 return RETURN_ERR;
8034 }
8035 while ((nread = getline(&line, &len, f)) != -1)
8036 {
8037 param = strtok(line,"=");
8038 value = strtok(NULL,"=");
8039
8040 if( strcmp("flags",param) == 0 )
8041 {
8042 value[strlen(value)-1]='\0';
8043 if(strstr (value,"AUTHORIZED") != NULL )
8044 {
8045 dev[auth_temp].cli_AuthenticationState = 1;
8046 dev[auth_temp].cli_Active = 1;
8047 auth_temp++;
8048 read_flag=1;
8049 }
8050 }
8051 if(read_flag==1)
8052 {
8053 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8054 {
8055 value[strlen(value)-1]='\0';
8056 sscanf(value, "%x:%x:%x:%x:%x:%x",
8057 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8058 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8059 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8060 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8061 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8062 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8063
8064 }
8065 else if( strcmp("rx_packets",param) == 0 )
8066 {
8067 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8068 }
8069
8070 else if( strcmp("tx_packets",param) == 0 )
8071 {
8072 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8073 }
8074
8075 else if( strcmp("rx_bytes",param) == 0 )
8076 {
8077 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8078 }
8079
8080 else if( strcmp("tx_bytes",param) == 0 )
8081 {
8082 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8083 mac_temp++;
8084 read_flag=0;
8085 }
8086 }
8087 }
8088
8089 *output_array_size = auth_temp;
8090 auth_temp=0;
8091 mac_temp=0;
8092 free(line);
8093 fclose(f);
8094#endif
8095 char interface_name[MAX_BUF_SIZE] = {0};
8096 char wifi_status[MAX_BUF_SIZE] = {0};
8097 char hostapdconf[MAX_BUF_SIZE] = {0};
8098
8099 wifi_associated_dev3_t *dev_array = NULL;
8100 ULONG wifi_count = 0;
8101
8102 *associated_dev_array = NULL;
8103 *output_array_size = 0;
8104
8105 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8106 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8107 {
8108 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8109
developerac6f1142022-12-20 19:26:35 +08008110 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008111
8112 if(strlen(interface_name) > 1)
8113 {
8114 wifihal_interfacestatus(wifi_status,interface_name);
8115 if(strcmp(wifi_status,"RUNNING") == 0)
8116 {
8117 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8118
8119 *associated_dev_array = dev_array;
8120 *output_array_size = wifi_count;
8121 }
8122 else
8123 {
8124 *associated_dev_array = NULL;
8125 }
8126 }
8127 }
8128
8129 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8130 return RETURN_OK;
8131}
8132#endif
8133
8134/* getIPAddress function */
8135/**
8136* @description Returning IpAddress of the Matched String
8137*
8138* @param
8139* @str Having MacAddress
8140* @ipaddr Having ipaddr
8141* @return The status of the operation
8142* @retval RETURN_OK if successful
8143* @retval RETURN_ERR if any error is detected
8144*
8145*/
8146
8147INT getIPAddress(char *str,char *ipaddr)
8148{
8149 FILE *fp = NULL;
8150 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8151 int LeaseTime = 0,ret = 0;
8152 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8153 {
8154 return RETURN_ERR;
8155 }
8156
8157 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8158 {
8159 /*
8160 Sample:sss
8161 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8162 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8163 */
8164 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008165 &(LeaseTime),
8166 phyAddr,
8167 ipAddr,
8168 hostName
8169 );
developer06a01d92022-09-07 16:32:39 +08008170 if(ret != 4)
8171 continue;
8172 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008173 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008174 }
developerd946fd62022-12-08 18:03:28 +08008175 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008176 return RETURN_OK;
8177}
8178
8179/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8180/**
8181* @description Returning Inactive wireless connected clients informations
8182*
8183* @param
8184* @filename Holding private_wifi 2g/5g content files
8185* @associated_dev_array Having inactiv wireless clients informations
8186* @output_array_size Returning Inactive wireless counts
8187* @return The status of the operation
8188* @retval RETURN_OK if successful
8189* @retval RETURN_ERR if any error is detected
8190*
8191*/
8192
8193INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8194{
8195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8196 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8197 FILE *fp = NULL;
8198 int arr[MACADDRESS_SIZE] = {0};
8199 unsigned char mac[MACADDRESS_SIZE] = {0};
8200 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8201 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8202 fp = popen(buf,"r");
8203 if(fp == NULL)
8204 return RETURN_ERR;
8205 else
8206 {
8207 fgets(path,sizeof(path),fp);
8208 maccount = atoi(path);
8209 }
8210 pclose(fp);
8211 *output_array_size = maccount;
8212 wifi_associated_dev3_t* temp = NULL;
8213 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8214 *associated_dev_array = temp;
8215 if(temp == NULL)
8216 {
8217 printf("Error Statement. Insufficient memory \n");
8218 return RETURN_ERR;
8219 }
8220 memset(buf,0,sizeof(buf));
8221 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8222 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008223 if (fp == NULL) {
8224 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8225 return RETURN_ERR;
8226 }
developer06a01d92022-09-07 16:32:39 +08008227 for(count = 0; count < maccount ; count++)
8228 {
8229 fgets(path,sizeof(path),fp);
8230 for(i = 0; path[i]!='\n';i++)
8231 str[i]=path[i];
8232 str[i]='\0';
8233 getIPAddress(str,ipaddr);
8234 memset(buf,0,sizeof(buf));
8235 if(strlen(ipaddr) > 0)
8236 {
8237 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8238 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8239 {
8240 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8241 {
8242 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8243 {
8244 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8245
8246 }
8247 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8248 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]);
8249 }
8250 temp[count].cli_AuthenticationState = 0; //TODO
8251 temp[count].cli_Active = 0; //TODO
8252 temp[count].cli_SignalStrength = 0;
8253 }
8254 else //Active wireless clients info
8255 {
8256 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8257 {
8258 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8259 {
8260 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8261
8262 }
8263 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8264 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]);
8265 }
8266 temp[count].cli_Active = 1;
8267 }
8268 }
8269 memset(ipaddr,0,sizeof(ipaddr));
8270 }
8271 pclose(fp);
8272 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8273 return RETURN_OK;
8274}
8275//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8276//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8277//To get Band Steering Capability
8278INT wifi_getBandSteeringCapability(BOOL *support)
8279{
8280 *support = FALSE;
8281 return RETURN_OK;
8282}
8283
8284
8285//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8286//To get Band Steering enable status
8287INT wifi_getBandSteeringEnable(BOOL *enable)
8288{
8289 *enable = FALSE;
8290 return RETURN_OK;
8291}
8292
8293//To turn on/off Band steering
8294INT wifi_setBandSteeringEnable(BOOL enable)
8295{
8296 return RETURN_OK;
8297}
8298
8299//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8300//To get Band Steering AP group
8301INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8302{
8303 if (NULL == output_ApGroup)
8304 return RETURN_ERR;
8305
8306 strcpy(output_ApGroup, "1,2");
8307 return RETURN_OK;
8308}
8309
8310//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8311//to set and read the band steering BandUtilizationThreshold parameters
8312INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8313{
8314 return RETURN_ERR;
8315}
8316
8317INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8318{
8319 return RETURN_ERR;
8320}
8321
8322//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8323//to set and read the band steering RSSIThreshold parameters
8324INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8325{
8326 return RETURN_ERR;
8327}
8328
8329INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8330{
8331 return RETURN_ERR;
8332}
8333
8334
8335//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8336//to set and read the band steering physical modulation rate threshold parameters
8337INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8338{
8339 //If chip is not support, return -1
8340 return RETURN_ERR;
8341}
8342
8343INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8344{
8345 //If chip is not support, return -1
8346 return RETURN_ERR;
8347}
8348
8349//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8350//to set and read the inactivity time (in seconds) for steering under overload condition
8351INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8352{
8353 return RETURN_ERR;
8354}
8355
8356INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8357{
8358 return RETURN_ERR;
8359}
8360
8361//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8362//to set and read the inactivity time (in seconds) for steering under Idle condition
8363INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8364{
8365 return RETURN_ERR;
8366}
8367
8368INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8369{
8370 return RETURN_ERR;
8371}
8372
8373//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8374//pClientMAC[64]
8375//pSourceSSIDIndex[64]
8376//pDestSSIDIndex[64]
8377//pSteeringReason[256]
8378INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8379{
8380 //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
8381 *pSteeringTime=time(NULL);
8382 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8383 return RETURN_OK;
8384}
8385
8386INT wifi_ifConfigDown(INT apIndex)
8387{
8388 INT status = RETURN_OK;
8389 char cmd[64];
8390
8391 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8392 printf("%s: %s\n", __func__, cmd);
8393 system(cmd);
8394
8395 return status;
8396}
8397
8398INT wifi_ifConfigUp(INT apIndex)
8399{
developerd946fd62022-12-08 18:03:28 +08008400 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008401 char cmd[128];
8402 char buf[1024];
8403
developerac6f1142022-12-20 19:26:35 +08008404 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008405 return RETURN_ERR;
8406 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008407 _syscmd(cmd, buf, sizeof(buf));
8408 return 0;
8409}
8410
8411//>> Deprecated. Replace with wifi_applyRadioSettings
8412INT wifi_pushBridgeInfo(INT apIndex)
8413{
developerd946fd62022-12-08 18:03:28 +08008414 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008415 char ip[32] = {0};
8416 char subnet[32] = {0};
8417 char bridge[32] = {0};
8418 int vlanId = 0;
8419 char cmd[128] = {0};
8420 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008421
8422 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8423 wifi_getApVlanID(apIndex,&vlanId);
8424
developerac6f1142022-12-20 19:26:35 +08008425 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008426 return RETURN_ERR;
8427 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008428 _syscmd(cmd,buf, sizeof(buf));
8429
8430 return 0;
8431}
8432
8433INT wifi_pushChannel(INT radioIndex, UINT channel)
8434{
developerd946fd62022-12-08 18:03:28 +08008435 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008436 char cmd[128];
8437 char buf[1024];
8438 int apIndex;
8439
8440 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008441 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008442 return RETURN_ERR;
8443 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008444 _syscmd(cmd,buf, sizeof(buf));
8445
8446 return 0;
8447}
8448
8449INT wifi_pushChannelMode(INT radioIndex)
8450{
8451 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8452 return RETURN_ERR;
8453}
8454
8455INT wifi_pushDefaultValues(INT radioIndex)
8456{
8457 //Apply Comcast specified default radio settings instantly
8458 //AMPDU=1
8459 //AMPDUFrames=32
8460 //AMPDULim=50000
8461 //txqueuelen=1000
8462
8463 return RETURN_ERR;
8464}
8465
8466INT wifi_pushTxChainMask(INT radioIndex)
8467{
8468 //Apply default TxChainMask instantly
8469 return RETURN_ERR;
8470}
8471
8472INT wifi_pushRxChainMask(INT radioIndex)
8473{
8474 //Apply default RxChainMask instantly
8475 return RETURN_ERR;
8476}
8477
8478INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8479{
8480 INT status;
8481
8482 status = wifi_setSSIDName(apIndex,ssid);
8483 wifi_setApEnable(apIndex,FALSE);
8484 wifi_setApEnable(apIndex,TRUE);
8485
8486 return status;
8487}
8488
8489INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8490{
8491 //Apply default Ssid Advertisement instantly
8492 return RETURN_ERR;
8493}
8494
8495INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8496{
8497 INT status = RETURN_ERR;
8498 *output = 0;
8499 return RETURN_ERR;
8500}
8501
8502INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8503{
8504 return RETURN_OK;
8505}
8506
8507INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8508{
8509 return RETURN_OK;
8510}
8511
8512//To-do
8513INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8514{
developereb199ae2022-09-13 14:04:27 +08008515 char output[16]={'\0'};
8516 char config_file[MAX_BUF_SIZE] = {0};
8517
8518 if (!output_string)
8519 return RETURN_ERR;
8520
8521 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8522 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8523
8524 if (strlen(output) == 0)
8525 snprintf(output_string, 64, "Disabled");
8526 else if (strncmp(output, "0", 1) == 0)
8527 snprintf(output_string, 64, "Disabled");
8528 else if (strncmp(output, "1", 1) == 0)
8529 snprintf(output_string, 64, "Optional");
8530 else if (strncmp(output, "2", 1) == 0)
8531 snprintf(output_string, 64, "Required");
8532 else {
8533 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8534 return RETURN_ERR;
8535 }
8536
8537 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008538 return RETURN_OK;
8539}
8540INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8541{
developereb199ae2022-09-13 14:04:27 +08008542 char str[MAX_BUF_SIZE]={'\0'};
8543 char cmd[MAX_CMD_SIZE]={'\0'};
8544 struct params params;
8545 char config_file[MAX_BUF_SIZE] = {0};
8546
8547 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8548 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8549 return RETURN_ERR;
8550
8551 params.name = "ieee80211w";
8552 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8553 params.value = "0";
8554 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8555 params.value = "1";
8556 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8557 params.value = "2";
8558 else{
8559 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8560 return RETURN_ERR;
8561 }
8562 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8563 wifi_hostapdWrite(config_file, &params, 1);
8564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008565 return RETURN_OK;
8566}
8567INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8568{
8569 char output[16]={'\0'};
8570 char config_file[MAX_BUF_SIZE] = {0};
8571
8572 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8573 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8574 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8575
8576 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8577 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8578
8579 return RETURN_OK;
8580}
8581
8582INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8583{
8584 return RETURN_OK;
8585}
8586
8587INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8588{
8589 return RETURN_OK;
8590}
8591
8592INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8593{
8594 return RETURN_OK;
8595}
8596
8597INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8598{
8599 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8600 char config_file[MAX_BUF_SIZE] = {0};
8601
8602 if (NULL == output)
8603 return RETURN_ERR;
8604 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8605 wifi_hostapdRead(config_file,"hw_mode",output,64);
8606
8607 if(strcmp(output,"b")==0)
8608 sprintf(output, "%s", "1,2,5.5,11");
8609 else if (strcmp(output,"a")==0)
8610 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8611 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8612 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8613
8614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8615 return RETURN_OK;
8616}
8617
8618INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8619{
8620 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8621 char *temp;
8622 char temp_output[128];
8623 char temp_TransmitRates[128];
8624 char config_file[MAX_BUF_SIZE] = {0};
8625
8626 if (NULL == output)
8627 return RETURN_ERR;
8628
8629 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8630 wifi_hostapdRead(config_file,"supported_rates",output,64);
8631
developer5b398df2022-11-17 20:39:48 +08008632 if (strlen(output) == 0) {
8633 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8634 return RETURN_OK;
8635 }
developer06a01d92022-09-07 16:32:39 +08008636 strcpy(temp_TransmitRates,output);
8637 strcpy(temp_output,"");
8638 temp = strtok(temp_TransmitRates," ");
8639 while(temp!=NULL)
8640 {
8641 temp[strlen(temp)-1]=0;
8642 if((temp[0]=='5') && (temp[1]=='\0'))
8643 {
8644 temp="5.5";
8645 }
8646 strcat(temp_output,temp);
8647 temp = strtok(NULL," ");
8648 if(temp!=NULL)
8649 {
8650 strcat(temp_output,",");
8651 }
8652 }
8653 strcpy(output,temp_output);
8654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8655
8656 return RETURN_OK;
8657}
8658
8659INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8660{
8661 return RETURN_OK;
8662}
8663
8664
8665INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8666{
8667 int i=0;
8668 char *temp;
developeref938762022-10-19 17:21:01 +08008669 char temp1[128] = {0};
8670 char temp_output[128] = {0};
8671 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008672 struct params params={'\0'};
8673 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008674 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008675
8676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8677 if(NULL == output)
8678 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008679 strcpy(temp_TransmitRates,output);
8680
8681 for(i=0;i<strlen(temp_TransmitRates);i++)
8682 {
developeref938762022-10-19 17:21:01 +08008683 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008684 {
8685 continue;
8686 }
8687 else
8688 {
8689 return RETURN_ERR;
8690 }
8691 }
8692 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008693 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008694 while(temp!=NULL)
8695 {
8696 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008697 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008698 {
developeref938762022-10-19 17:21:01 +08008699 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008700 {
8701 return RETURN_ERR;
8702 }
8703 }
8704
8705 if(strcmp(temp,"5.5")==0)
8706 {
8707 strcpy(temp1,"55");
8708 }
8709 else
8710 {
8711 strcat(temp1,"0");
8712 }
8713 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008714 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008715 if(temp!=NULL)
8716 {
8717 strcat(temp_output," ");
8718 }
8719 }
8720 strcpy(output,temp_output);
8721
developer06a01d92022-09-07 16:32:39 +08008722 params.name = "supported_rates";
8723 params.value = output;
8724
8725 wifi_dbg_printf("\n%s:",__func__);
8726 wifi_dbg_printf("params.value=%s\n",params.value);
8727 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8728 wifi_hostapdWrite(config_file,&params,1);
8729 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8730
8731 return RETURN_OK;
8732}
8733
8734
8735static char *sncopy(char *dst, int dst_sz, const char *src)
8736{
8737 if (src && dst && dst_sz > 0) {
8738 strncpy(dst, src, dst_sz);
8739 dst[dst_sz - 1] = '\0';
8740 }
8741 return dst;
8742}
8743
8744static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8745{
8746 if (0 == strcmp(ht_mode, "HT40") ||
8747 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008748 0 == strcmp(ht_mode, "HT160") ||
8749 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008750 switch (channel) {
developer9a520b12023-09-21 16:01:43 +08008751 case 0 ... 7:
developer06a01d92022-09-07 16:32:39 +08008752 case 36:
8753 case 44:
8754 case 52:
8755 case 60:
8756 case 100:
8757 case 108:
8758 case 116:
8759 case 124:
8760 case 132:
8761 case 140:
8762 case 149:
8763 case 157:
8764 return 1;
8765 case 8 ... 13:
8766 case 40:
8767 case 48:
8768 case 56:
8769 case 64:
8770 case 104:
8771 case 112:
8772 case 120:
8773 case 128:
8774 case 136:
8775 case 144:
8776 case 153:
8777 case 161:
8778 return -1;
8779 default:
8780 return -EINVAL;
8781 }
8782 }
8783
8784 return -EINVAL;
8785}
8786
developerb7593de2022-10-18 09:51:57 +08008787static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8788{
8789 int idx = channel%8;
8790 if (0 == strcmp(ht_mode, "HT40") ||
8791 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008792 0 == strcmp(ht_mode, "HT160") ||
8793 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008794 switch (idx) {
8795 case 1:
8796 return 1;
8797 case 5:
8798 return -1;
8799 default:
8800 return -EINVAL;
8801 }
8802 }
8803
8804 return -EINVAL;
8805}
developer06a01d92022-09-07 16:32:39 +08008806static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8807{
8808 if (NULL == hw_mode) return;
8809
8810 if (0 == strcmp(hw_mode, "ac"))
8811 sncopy(bw_mode, bw_mode_len, "ht vht");
8812
8813 if (0 == strcmp(hw_mode, "n"))
8814 sncopy(bw_mode, bw_mode_len, "ht");
8815
8816 return;
8817}
8818
8819static int util_chan_to_freq(int chan)
8820{
8821 if (chan == 14)
8822 return 2484;
8823 else if (chan < 14)
8824 return 2407 + chan * 5;
8825 else if (chan >= 182 && chan <= 196)
8826 return 4000 + chan * 5;
8827 else
8828 return 5000 + chan * 5;
8829 return 0;
8830}
8831
developerb7593de2022-10-18 09:51:57 +08008832static int util_6G_chan_to_freq(int chan)
8833{
8834 if (chan)
8835 return 5950 + chan * 5;
8836 else
8837 return 0;
8838
8839}
developer06a01d92022-09-07 16:32:39 +08008840const int *util_unii_5g_chan2list(int chan, int width)
8841{
8842 static const int lists[] = {
8843 // <width>, <chan1>, <chan2>..., 0,
8844 20, 36, 0,
8845 20, 40, 0,
8846 20, 44, 0,
8847 20, 48, 0,
8848 20, 52, 0,
8849 20, 56, 0,
8850 20, 60, 0,
8851 20, 64, 0,
8852 20, 100, 0,
8853 20, 104, 0,
8854 20, 108, 0,
8855 20, 112, 0,
8856 20, 116, 0,
8857 20, 120, 0,
8858 20, 124, 0,
8859 20, 128, 0,
8860 20, 132, 0,
8861 20, 136, 0,
8862 20, 140, 0,
8863 20, 144, 0,
8864 20, 149, 0,
8865 20, 153, 0,
8866 20, 157, 0,
8867 20, 161, 0,
8868 20, 165, 0,
8869 40, 36, 40, 0,
8870 40, 44, 48, 0,
8871 40, 52, 56, 0,
8872 40, 60, 64, 0,
8873 40, 100, 104, 0,
8874 40, 108, 112, 0,
8875 40, 116, 120, 0,
8876 40, 124, 128, 0,
8877 40, 132, 136, 0,
8878 40, 140, 144, 0,
8879 40, 149, 153, 0,
8880 40, 157, 161, 0,
8881 80, 36, 40, 44, 48, 0,
8882 80, 52, 56, 60, 64, 0,
8883 80, 100, 104, 108, 112, 0,
8884 80, 116, 120, 124, 128, 0,
8885 80, 132, 136, 140, 144, 0,
8886 80, 149, 153, 157, 161, 0,
8887 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8888 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8889 -1 // final delimiter
8890 };
8891 const int *start;
8892 const int *p;
8893
8894 for (p = lists; *p != -1; p++) {
8895 if (*p == width) {
8896 for (start = ++p; *p != 0; p++) {
8897 if (*p == chan)
8898 return start;
8899 }
8900 }
8901 // move to the end of channel list of given width
8902 while (*p != 0) {
8903 p++;
8904 }
8905 }
8906
8907 return NULL;
8908}
8909
8910static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8911{
8912 if (NULL == ht_mode)
8913 return 0;
8914
8915 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8916 const int *chans = util_unii_5g_chan2list(channel, width);
8917 int sum = 0;
8918 int cnt = 0;
8919
8920 if (NULL == chans)
8921 return 0;
8922
8923 while (*chans) {
8924 sum += *chans;
8925 cnt++;
8926 chans++;
8927 }
developer30423732022-12-01 16:17:49 +08008928 if (cnt == 0)
8929 return 0;
developer06a01d92022-09-07 16:32:39 +08008930 return sum / cnt;
8931}
8932
developerb7593de2022-10-18 09:51:57 +08008933static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8934{
8935 if (NULL == ht_mode)
8936 return 0;
8937
8938 int width = strtol((ht_mode + 2), NULL, 10);
8939
8940 int idx = 0 ;
8941 int centerchan = 0;
8942 int chan_ofs = 1;
8943
8944 if (width == 40){
8945 idx = ((channel/4) + chan_ofs)%2;
8946 switch (idx) {
8947 case 0:
8948 centerchan = (channel - 2);
8949 break;
8950 case 1:
8951 centerchan = (channel + 2);
8952 break;
8953 default:
8954 return -EINVAL;
8955 }
8956 }else if (width == 80){
8957 idx = ((channel/4) + chan_ofs)%4;
8958 switch (idx) {
8959 case 0:
8960 centerchan = (channel - 6);
8961 break;
8962 case 1:
8963 centerchan = (channel + 6);
8964 break;
8965 case 2:
8966 centerchan = (channel + 2);
8967 break;
8968 case 3:
8969 centerchan = (channel - 2);
8970 break;
8971 default:
8972 return -EINVAL;
8973 }
8974 }else if (width == 160){
8975 switch (channel) {
8976 case 1 ... 29:
8977 centerchan = 15;
8978 break;
8979 case 33 ... 61:
8980 centerchan = 47;
8981 break;
8982 case 65 ... 93:
8983 centerchan = 79;
8984 break;
8985 case 97 ... 125:
8986 centerchan = 111;
8987 break;
8988 case 129 ... 157:
8989 centerchan = 143;
8990 break;
8991 case 161 ... 189:
8992 centerchan = 175;
8993 break;
8994 case 193 ... 221:
8995 centerchan = 207;
8996 break;
8997 default:
8998 return -EINVAL;
8999 }
developer7c4cd202023-03-01 10:56:29 +08009000 }else if (width == 320){
9001 switch (channel) {
9002 case 1 ... 29:
9003 centerchan = 31;
9004 break;
9005 case 33 ... 93:
9006 centerchan = 63;
9007 break;
9008 case 97 ... 157:
9009 centerchan = 127;
9010 break;
9011 case 161 ... 221:
9012 centerchan = 191;
9013 break;
9014 default:
9015 return -EINVAL;
9016 }
developerb7593de2022-10-18 09:51:57 +08009017 }
9018 return centerchan;
9019}
developer06a01d92022-09-07 16:32:39 +08009020static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9021{
9022 BOOL onlyG, onlyN, onlyA;
9023 CHAR tmp[64];
9024 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9025 if (ret == RETURN_OK) {
9026 sncopy(hw_mode, hw_mode_size, tmp);
9027 }
9028 return ret;
9029}
9030
9031INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9032{
9033 // Sample commands:
9034 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9035 // hostapd_cli -i wifi0 chan_switch 30 2437
9036 char cmd[MAX_CMD_SIZE] = {0};
9037 char buf[MAX_BUF_SIZE] = {0};
9038 int freq = 0, ret = 0;
9039 char center_freq1_str[32] = ""; // center_freq1=%d
9040 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9041 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9042 char hw_mode[16] = ""; // n|ac
9043 char bw_mode[16] = ""; // ht|ht vht
9044 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08009045 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009046 int sec_chan_offset;
9047 int width;
developer4fb0b922022-09-30 14:29:09 +08009048 char config_file[64] = {0};
9049 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08009050 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08009051 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08009052 wifi_band band = band_invalid;
9053 int center_chan = 0;
9054 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08009055
developer4fb0b922022-09-30 14:29:09 +08009056 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08009057
developerac6f1142022-12-20 19:26:35 +08009058 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009059 return RETURN_ERR;
9060
developer06a01d92022-09-07 16:32:39 +08009061 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9062
developerb7593de2022-10-18 09:51:57 +08009063 band = wifi_index_to_band(radioIndex);
9064
developer5884e982022-10-06 10:52:50 +08009065 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08009066
9067 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08009068 if (channel){
developerb7593de2022-10-18 09:51:57 +08009069 if (band == band_6){
9070 freq = util_6G_chan_to_freq(channel);
9071 }else{
9072 freq = util_chan_to_freq(channel);
9073 }
developer7c4cd202023-03-01 10:56:29 +08009074 if (width == 320) {
9075 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
9076 setEHT320 = TRUE;
9077 }
developer5884e982022-10-06 10:52:50 +08009078 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08009079
developer5884e982022-10-06 10:52:50 +08009080 // Provide bandwith if specified
9081 if (channel_width_MHz > 20) {
9082 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9083 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9084 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08009085
developer5884e982022-10-06 10:52:50 +08009086 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9087 }else if (channel_width_MHz == 20){
9088 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9089 }
developer06a01d92022-09-07 16:32:39 +08009090
developerb7593de2022-10-18 09:51:57 +08009091
developer5884e982022-10-06 10:52:50 +08009092 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08009093 if (band == band_6){
9094 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9095 if(center_chan){
9096 center_freq1 = util_6G_chan_to_freq(center_chan);
9097 }
9098 }else{
9099 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9100 if(center_chan){
9101 center_freq1 = util_chan_to_freq(center_chan);
9102 }
developer5884e982022-10-06 10:52:50 +08009103 }
developerb7593de2022-10-18 09:51:57 +08009104
9105 if (center_freq1)
9106 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9107
9108 }
9109
9110 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9111 if (band == band_6){
9112 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9113 }else{
9114 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009115 }
developerb7593de2022-10-18 09:51:57 +08009116 if (sec_chan_offset != -EINVAL)
9117 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009118
developer5884e982022-10-06 10:52:50 +08009119 // Only the first AP, other are hanging on the same radio
9120 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009121 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9122 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009123 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9124 wifi_dbg_printf("execute: '%s'\n", cmd);
9125 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009126 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009127
developer5884e982022-10-06 10:52:50 +08009128 ret = wifi_setRadioChannel(radioIndex, channel);
9129 if (ret != RETURN_OK) {
9130 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9131 return RETURN_ERR;
9132 }
9133
9134 if (sec_chan_offset == 1) ext_str = "Above";
9135 else if (sec_chan_offset == -1) ext_str = "Below";
9136
9137 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009138
developer5884e982022-10-06 10:52:50 +08009139 } else {
9140 if (channel_width_MHz > 20)
9141 ext_str = "Above";
9142 }
developer4fb0b922022-09-30 14:29:09 +08009143
developer06a01d92022-09-07 16:32:39 +08009144 char mhz_str[16];
9145 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009146 if (setEHT320 == TRUE)
9147 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9148 else
9149 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009150
developer57fa24a2023-03-15 17:25:07 +08009151 writeBandWidth(radioIndex, mhz_str);
9152 if (band == band_2_4 || band == band_5) {
9153 if (width == 20)
9154 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9155 else
9156 wifi_setRadioExtChannel(radioIndex, ext_str);
9157 }
developer06a01d92022-09-07 16:32:39 +08009158 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9159
9160 return RETURN_OK;
9161}
9162
9163INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9164{
developer615510b2022-09-27 10:14:35 +08009165 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009166 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009167 char cmd[256]={0};
9168 char buf[128]={0};
9169 char file_name[32] = {0};
9170 char filter_SSID[32] = {0};
9171 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009172 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009173 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009174 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009175 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009176 size_t len=0;
9177 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009178 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009179 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009180 bool filter_enable = false;
9181 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009182 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009183
developer615510b2022-09-27 10:14:35 +08009184 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009185
developer615510b2022-09-27 10:14:35 +08009186 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9187 f = fopen(file_name, "r");
9188 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009189 fgets(buf, sizeof(file_name), f);
9190 if ((strncmp(buf, "0", 1)) != 0) {
9191 fgets(filter_SSID, sizeof(file_name), f);
9192 if (strlen(filter_SSID) != 0)
9193 filter_enable = true;
9194 }
developer615510b2022-09-27 10:14:35 +08009195 fclose(f);
9196 }
9197
developerac6f1142022-12-20 19:26:35 +08009198 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009199 return RETURN_ERR;
9200
developer033b37b2022-10-18 11:27:46 +08009201 phyId = radio_index_to_phy(radio_index);
9202
9203 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009204 _syscmd(cmd, buf, sizeof(buf));
9205 channels_num = strtol(buf, NULL, 10);
9206
developerd946fd62022-12-08 18:03:28 +08009207 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9208 // 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 +08009209 fprintf(stderr, "cmd: %s\n", cmd);
9210 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009211 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9212 return RETURN_ERR;
9213 }
developer5550e242022-09-30 09:59:32 +08009214
9215 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9216 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9217
developer615510b2022-09-27 10:14:35 +08009218 ret = fgets(line, sizeof(line), f);
9219 while (ret != NULL) {
9220 if(strstr(line, "BSS") != NULL) { // new neighbor info
9221 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9222 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9223 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9224
9225 if (!filter_BSS) {
9226 index++;
9227 wifi_neighbor_ap2_t *tmp;
9228 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9229 if (tmp == NULL) { // no more memory to use
9230 index--;
9231 wifi_dbg_printf("%s: realloc failed\n", __func__);
9232 break;
9233 }
9234 scan_array = tmp;
9235 }
9236 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009237
developer615510b2022-09-27 10:14:35 +08009238 filter_BSS = false;
9239 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9240 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9241 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9242 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9243 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009244 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009245 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009246
developer615510b2022-09-27 10:14:35 +08009247 if (freq >= 2412 && freq <= 2484) {
9248 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9249 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9250 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9251 }
9252 else if (freq >= 5160 && freq <= 5805) {
9253 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9254 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9255 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9256 }
developer06a01d92022-09-07 16:32:39 +08009257
developer615510b2022-09-27 10:14:35 +08009258 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009259 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009260 for (int i = 0; i < channels_num; i++) {
9261 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9262 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9263 break;
9264 }
9265 }
developer06a01d92022-09-07 16:32:39 +08009266 }
developer615510b2022-09-27 10:14:35 +08009267 } else if (strstr(line, "beacon interval") != NULL) {
9268 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9269 } else if (strstr(line, "signal") != NULL) {
9270 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9271 } else if (strstr(line,"SSID") != NULL) {
9272 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9273 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9274 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009275 }
developer615510b2022-09-27 10:14:35 +08009276 } else if (strstr(line, "Supported rates") != NULL) {
9277 char SRate[80] = {0}, *tmp = NULL;
9278 memset(buf, 0, sizeof(buf));
9279 strcpy(SRate, line);
9280 tmp = strtok(SRate, ":");
9281 tmp = strtok(NULL, ":");
9282 strcpy(buf, tmp);
9283 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009284
developer615510b2022-09-27 10:14:35 +08009285 tmp = strtok(buf, " \n");
9286 while (tmp != NULL) {
9287 strcat(SRate, tmp);
9288 if (SRate[strlen(SRate) - 1] == '*') {
9289 SRate[strlen(SRate) - 1] = '\0';
9290 }
9291 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009292
developer615510b2022-09-27 10:14:35 +08009293 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009294 }
developer615510b2022-09-27 10:14:35 +08009295 SRate[strlen(SRate) - 1] = '\0';
9296 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9297 } else if (strstr(line, "DTIM") != NULL) {
9298 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9299 } else if (strstr(line, "VHT capabilities") != NULL) {
9300 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9301 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9302 } else if (strstr(line, "HT capabilities") != NULL) {
9303 strcat(scan_array[index].ap_SupportedStandards, ",n");
9304 strcpy(scan_array[index].ap_OperatingStandards, "n");
9305 } else if (strstr(line, "VHT operation") != NULL) {
9306 ret = fgets(line, sizeof(line), f);
9307 sscanf(line," * channel width: %d", &vht_channel_width);
9308 if(vht_channel_width == 1) {
9309 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9310 } else {
9311 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9312 }
9313 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9314 continue;
9315 } else if (strstr(line, "HT operation") != NULL) {
9316 ret = fgets(line, sizeof(line), f);
9317 sscanf(line," * secondary channel offset: %s", &buf);
9318 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009319 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009320 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 +08009321 }
developer615510b2022-09-27 10:14:35 +08009322 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009323 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009324 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9325 } else {
9326 //20Mhz
9327 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 +08009328 }
developer615510b2022-09-27 10:14:35 +08009329 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009330 continue;
developer615510b2022-09-27 10:14:35 +08009331 } else if (strstr(line, "HE capabilities") != NULL) {
9332 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9333 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9334 ret = fgets(line, sizeof(line), f);
9335 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9336 if (strstr(line, "HE40/2.4GHz") != NULL)
9337 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9338 else
9339 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9340 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9341 if (strstr(line, "HE80/5GHz") != NULL) {
9342 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9343 ret = fgets(line, sizeof(line), f);
9344 } else
9345 continue;
9346 if (strstr(line, "HE160/5GHz") != NULL)
9347 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009348 }
developer615510b2022-09-27 10:14:35 +08009349 continue;
9350 } else if (strstr(line, "WPA") != NULL) {
9351 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9352 } else if (strstr(line, "RSN") != NULL) {
9353 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9354 } else if (strstr(line, "Group cipher") != NULL) {
9355 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9356 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9357 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009358 }
developer06a01d92022-09-07 16:32:39 +08009359 }
developer615510b2022-09-27 10:14:35 +08009360 ret = fgets(line, sizeof(line), f);
9361 }
9362
9363 if (!filter_BSS) {
9364 *output_array_size = index + 1;
9365 } else {
9366 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9367 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009368 }
developer06a01d92022-09-07 16:32:39 +08009369 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009370 pclose(f);
developer5550e242022-09-30 09:59:32 +08009371 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009372 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009373 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009374}
developer615510b2022-09-27 10:14:35 +08009375
developer06a01d92022-09-07 16:32:39 +08009376INT wifi_getApAssociatedDeviceStats(
9377 INT apIndex,
9378 mac_address_t *clientMacAddress,
9379 wifi_associated_dev_stats_t *associated_dev_stats,
9380 u64 *handle)
9381{
9382 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9383 char interface_name[50] = {0};
9384 char cmd[1024] = {0};
9385 char mac_str[18] = {0};
9386 char *key = NULL;
9387 char *val = NULL;
9388 FILE *f = NULL;
9389 char *line = NULL;
9390 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009391
9392 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9393 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9394 return RETURN_ERR;
9395 }
9396
9397 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9398 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9399 if((f = popen(cmd, "r")) == NULL) {
9400 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9401 return RETURN_ERR;
9402 }
9403
developer30423732022-12-01 16:17:49 +08009404 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009405 key = strtok(line,":");
9406 val = strtok(NULL,":");
9407
9408 if(!strncmp(key,"rx bytes",8))
9409 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9410 if(!strncmp(key,"tx bytes",8))
9411 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9412 if(!strncmp(key,"rx packets",10))
9413 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9414 if(!strncmp(key,"tx packets",10))
9415 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9416 if(!strncmp(key,"tx retries",10))
9417 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9418 if(!strncmp(key,"tx failed",9))
9419 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9420 if(!strncmp(key,"rx drop misc",13))
9421 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9422 if(!strncmp(key,"rx bitrate",10)) {
9423 val = strtok(val, " ");
9424 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9425 }
9426 if(!strncmp(key,"tx bitrate",10)) {
9427 val = strtok(val, " ");
9428 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9429 }
9430 }
9431 free(line);
9432 pclose(f);
9433 return RETURN_OK;
9434}
9435
9436INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9437{
developerd946fd62022-12-08 18:03:28 +08009438 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009439 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9440
9441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9442 if (NULL == output_string)
9443 return RETURN_ERR;
9444
developerac6f1142022-12-20 19:26:35 +08009445 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009446 return RETURN_ERR;
9447 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 +08009448 _syscmd(cmd, buf, sizeof(buf));
9449
9450 //size of SSID name restricted to value less than 32 bytes
9451 snprintf(output_string, 32, "%s", buf);
9452 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9453
9454 return RETURN_OK;
9455}
9456
9457INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9458{
9459 //char cmd[MAX_CMD_SIZE] = {0};
9460 char config_file[MAX_BUF_SIZE] = {0};
9461 char buf[32] = {0};
9462
9463 if (!output_filterMode)
9464 return RETURN_ERR;
9465
9466 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9467 //_syscmd(cmd, buf, sizeof(buf));
9468 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9469 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009470 if(strlen(buf) == 0) {
9471 *output_filterMode = 0;
9472 }
9473 else {
9474 int macaddr_acl_mode = strtol(buf, NULL, 10);
9475 if (macaddr_acl_mode == 1) {
9476 *output_filterMode = 1;
9477 } else if (macaddr_acl_mode == 0) {
9478 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9479 if (strlen(buf) == 0) {
9480 *output_filterMode = 0;
9481 } else {
9482 *output_filterMode = 2;
9483 }
9484 } else {
9485 return RETURN_ERR;
9486 }
9487 }
developer06a01d92022-09-07 16:32:39 +08009488
9489 return RETURN_OK;
9490}
9491
9492INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9493{
9494 FILE *fp = NULL;
9495 char str[MAX_BUF_SIZE] = {0};
9496 int wificlientindex = 0 ;
9497 int count = 0;
9498 int signalstrength = 0;
9499 int arr[MACADDRESS_SIZE] = {0};
9500 unsigned char mac[MACADDRESS_SIZE] = {0};
9501 UINT wifi_count = 0;
9502 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9503 char pipeCmd[MAX_CMD_SIZE] = {0};
9504
9505 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9506 *output_array_size = 0;
9507 *associated_dev_array = NULL;
9508 char interface_name[50] = {0};
9509
9510 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9511 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9512 return RETURN_ERR;
9513 }
9514
9515 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9516 fp = popen(pipeCmd, "r");
9517 if (fp == NULL)
9518 {
9519 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9520 return RETURN_ERR;
9521 }
9522
9523 /* Read the output a line at a time - output it. */
9524 fgets(str, sizeof(str)-1, fp);
9525 wifi_count = (unsigned int) atoi ( str );
9526 *output_array_size = wifi_count;
9527 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9528 pclose(fp);
9529
9530 if(wifi_count == 0)
9531 {
9532 return RETURN_OK;
9533 }
9534 else
9535 {
9536 wifi_associated_dev2_t* temp = NULL;
9537 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9538 *associated_dev_array = temp;
9539 if(temp == NULL)
9540 {
9541 printf("Error Statement. Insufficient memory \n");
9542 return RETURN_ERR;
9543 }
9544
9545 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9546 system(pipeCmd);
9547
9548 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9549 if(fp == NULL)
9550 {
9551 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9552 return RETURN_ERR;
9553 }
9554 fclose(fp);
9555
developer30423732022-12-01 16:17:49 +08009556 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009557 fp = popen(pipeCmd, "r");
9558 if(fp)
9559 {
9560 for(count =0 ; count < wifi_count; count++)
9561 {
9562 fgets(str, MAX_BUF_SIZE, fp);
9563 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9564 {
9565 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9566 {
9567 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9568
9569 }
9570 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9571 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]);
9572 }
9573 temp[count].cli_AuthenticationState = 1; //TODO
9574 temp[count].cli_Active = 1; //TODO
9575 }
9576 pclose(fp);
9577 }
9578
9579 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009580 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 +08009581 fp = popen(pipeCmd, "r");
9582 if(fp)
9583 {
9584 pclose(fp);
9585 }
9586 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9587 if(fp)
9588 {
9589 for(count =0 ; count < wifi_count ;count++)
9590 {
9591 fgets(str, MAX_BUF_SIZE, fp);
9592 signalstrength = atoi(str);
9593 temp[count].cli_RSSI = signalstrength;
9594 }
9595 pclose(fp);
9596 }
9597
9598
9599 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009600 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 +08009601 fp = popen(pipeCmd, "r");
9602 if (fp)
9603 {
9604 pclose(fp);
9605 }
9606 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9607 if (fp)
9608 {
9609 for (count = 0; count < wifi_count; count++)
9610 {
9611 fgets(str, MAX_BUF_SIZE, fp);
9612 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9613 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9614 }
9615 pclose(fp);
9616 }
9617
9618 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009619 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 +08009620 fp = popen(pipeCmd, "r");
9621 if (fp)
9622 {
9623 pclose(fp);
9624 }
9625 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9626 if (fp)
9627 {
9628 for (count = 0; count < wifi_count; count++)
9629 {
9630 fgets(str, MAX_BUF_SIZE, fp);
9631 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9632 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9633 }
9634 pclose(fp);
9635 }
9636 }
9637 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9638 return RETURN_OK;
9639
9640}
9641
9642INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9643{
9644#if 0
9645 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009646 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009647 _syscmd(cmd, buf, sizeof(buf));*/
9648
9649 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9650 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9651 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9652 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9653
9654 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.
9655 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].
9656 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].
9657 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].
9658 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9659 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9660
9661 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9662 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9663 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9664 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.
9665 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.
9666 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.
9667 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.
9668 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.
9669 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.
9670 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.
9671 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9672#endif
9673
9674 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009675 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009676 char pipeCmd[128] = {0};
9677 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009678 wifi_ssidTrafficStats2_t *out = output_struct;
9679
developerce736392022-09-13 15:24:34 +08009680 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009681 if (!output_struct)
9682 return RETURN_ERR;
9683
developerce736392022-09-13 15:24:34 +08009684 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009685 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009686 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009687 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009688
developer06a01d92022-09-07 16:32:39 +08009689 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009690 if (fp == NULL) {
9691 fprintf(stderr, "%s: popen failed\n", __func__);
9692 return RETURN_ERR;
9693 }
9694 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009695 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009696
developerce736392022-09-13 15:24:34 +08009697 if (strlen(str) == 0) // interface not exist
9698 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009699
developerce736392022-09-13 15:24:34 +08009700 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9701 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009702
developerce736392022-09-13 15:24:34 +08009703 memset(str, 0, sizeof(str));
9704 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009705 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009706 if (fp == NULL) {
9707 fprintf(stderr, "%s: popen failed\n", __func__);
9708 return RETURN_ERR;
9709 }
9710 fgets(str, sizeof(str), fp);
9711
9712 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9713 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009714 pclose(fp);
developerce736392022-09-13 15:24:34 +08009715
9716 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9717 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9718
9719 // Not supported
9720 output_struct->ssid_RetransCount = 0;
9721 output_struct->ssid_FailedRetransCount = 0;
9722 output_struct->ssid_RetryCount = 0;
9723 output_struct->ssid_MultipleRetryCount = 0;
9724 output_struct->ssid_ACKFailureCount = 0;
9725 output_struct->ssid_AggregatedPacketCount = 0;
9726
developer06a01d92022-09-07 16:32:39 +08009727 return RETURN_OK;
9728}
9729
9730//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).
9731INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9732{
9733 char output_val[16]={'\0'};
9734 char config_file[MAX_BUF_SIZE] = {0};
9735
9736 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9737 if (!output)
9738 return RETURN_ERR;
9739 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9740 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9741
9742 if( strcmp(output_val,"1") == 0 )
9743 *output = TRUE;
9744 else
9745 *output = FALSE;
9746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9747
9748 return RETURN_OK;
9749}
9750
9751INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9752{
9753 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9754 char str[MAX_BUF_SIZE]={'\0'};
9755 char string[MAX_BUF_SIZE]={'\0'};
9756 char cmd[MAX_CMD_SIZE]={'\0'};
9757 char *ch;
9758 char config_file[MAX_BUF_SIZE] = {0};
9759 struct params params;
9760
9761 if(enable == TRUE)
9762 strcpy(string,"1");
9763 else
9764 strcpy(string,"0");
9765
9766 params.name = "ap_isolate";
9767 params.value = string;
9768
9769 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9770 wifi_hostapdWrite(config_file,&params,1);
9771 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9772
9773 return RETURN_OK;
9774}
9775
9776INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9777{
9778 if (NULL == output_dBm)
9779 return RETURN_ERR;
9780
9781 *output_dBm = 0;
9782 return RETURN_OK;
9783}
9784
9785INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9786{
9787 return RETURN_OK;
9788}
9789INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9790{
9791 return RETURN_OK;
9792}
9793INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9794{
9795 return RETURN_OK;
9796}
9797INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9798{
9799 return RETURN_OK;
9800}
9801INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9802{
9803 return RETURN_OK;
9804}
9805INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9806{
9807 char config_file[MAX_BUF_SIZE] = {0};
9808 struct params list;
9809
9810 list.name = "bss_transition";
9811 list.value = activate?"1":"0";
9812 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9813 wifi_hostapdWrite(config_file, &list, 1);
9814
9815 return RETURN_OK;
9816}
9817wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9818
9819void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9820{
9821 return;
9822}
9823
9824INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9825{
9826 // TODO Implement me!
9827 return RETURN_OK;
9828}
9829
9830INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9831{
developera3c68b92022-09-13 15:27:29 +08009832 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009833 FILE *f = NULL;
9834
developer72ec5572023-01-05 16:27:13 +08009835 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009836
developer72ec5572023-01-05 16:27:13 +08009837 if (essid == NULL)
9838 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009839
developer72ec5572023-01-05 16:27:13 +08009840 if (strlen(essid) == 0 || apIndex == -1) {
9841 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9842 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009843 }
9844
developer72ec5572023-01-05 16:27:13 +08009845 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9846 f = fopen(file_name, "w");
9847 if (f == NULL)
9848 return RETURN_ERR;
9849
9850 // For mode == 0 is to disable filter, just don't write ssid to the file.
9851 fprintf(f, "%d\n%s", mode, mode?essid:"");
9852 fclose(f);
9853 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009854 return RETURN_OK;
9855}
9856
9857INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9858{
9859 // TODO Implement me!
9860 //Apply wifi_pushRadioChannel() instantly
9861 return RETURN_ERR;
9862}
9863
9864INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9865{
9866 // TODO Implement me!
9867 return RETURN_OK;
9868}
9869
9870#ifdef HAL_NETLINK_IMPL
9871static int tidStats_callback(struct nl_msg *msg, void *arg) {
9872 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9873 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9874 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9875 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9876 int rem , tid_index = 0;
9877
9878 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9879 wifi_associated_dev_tid_entry_t *stats_entry;
9880
9881 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9882 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9883 };
9884 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9885 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9886 };
9887
9888 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9889 genlmsg_attrlen(gnlh, 0), NULL);
9890
9891
9892 if (!tb[NL80211_ATTR_STA_INFO]) {
9893 fprintf(stderr, "station stats missing!\n");
9894 return NL_SKIP;
9895 }
9896
9897 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9898 tb[NL80211_ATTR_STA_INFO],
9899 stats_policy)) {
9900 fprintf(stderr, "failed to parse nested attributes!\n");
9901 return NL_SKIP;
9902 }
9903
9904 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9905 {
9906 stats_entry = &out->tid_array[tid_index];
9907
9908 stats_entry->tid = tid_index;
9909 stats_entry->ac = _tid_ac_index_get[tid_index];
9910
9911 if(sinfo[NL80211_STA_INFO_TID_STATS])
9912 {
9913 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9914 printf("failed to parse nested stats attributes!");
9915 return NL_SKIP;
9916 }
9917 }
9918 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9919 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9920
9921 if(tid_index < (PS_MAX_TID - 1))
9922 tid_index++;
9923 }
9924 //ToDo: sum_time_ms, ewma_time_ms
9925 return NL_SKIP;
9926}
9927#endif
9928
9929INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9930{
9931#ifdef HAL_NETLINK_IMPL
9932 Netlink nl;
9933 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009934 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009935
developerac6f1142022-12-20 19:26:35 +08009936 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009937 return RETURN_ERR;
9938
9939 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009940
9941 nl.id = initSock80211(&nl);
9942
9943 if (nl.id < 0) {
9944 fprintf(stderr, "Error initializing netlink \n");
9945 return -1;
9946 }
9947
9948 struct nl_msg* msg = nlmsg_alloc();
9949
9950 if (!msg) {
9951 fprintf(stderr, "Failed to allocate netlink message.\n");
9952 nlfree(&nl);
9953 return -2;
9954 }
9955
9956 genlmsg_put(msg,
9957 NL_AUTO_PORT,
9958 NL_AUTO_SEQ,
9959 nl.id,
9960 0,
9961 0,
9962 NL80211_CMD_GET_STATION,
9963 0);
9964
9965 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9966 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9967 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9968 nl_send_auto(nl.socket, msg);
9969 nl_recvmsgs(nl.socket, nl.cb);
9970 nlmsg_free(msg);
9971 nlfree(&nl);
9972 return RETURN_OK;
9973#else
9974//iw implementation
9975#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9976#define TOTAL_MAX_LINES 50
9977
9978 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009979 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009980 FILE *fp=NULL;
9981 char pipeCmd[1024]= {'\0'};
9982 int lines,tid_index=0;
9983 char mac_addr[20] = {'\0'};
9984
developerac6f1142022-12-20 19:26:35 +08009985 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009986 return RETURN_ERR;
9987
developer06a01d92022-09-07 16:32:39 +08009988 wifi_associated_dev_tid_entry_t *stats_entry;
9989
developer06a01d92022-09-07 16:32:39 +08009990 strcpy(mac_addr,clientMacAddress);
9991
9992 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9993 fp= popen(pipeCmd,"r");
9994 if(fp == NULL)
9995 {
9996 perror("popen for station dump failed\n");
9997 return RETURN_ERR;
9998 }
9999 pclose(fp);
10000
10001 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10002 fp=popen(pipeCmd,"r");
10003 if(fp == NULL)
10004 {
10005 perror("popen for grep station failed\n");
10006 return RETURN_ERR;
10007 }
10008 else if(fgets(buf,sizeof(buf),fp) != NULL)
10009 lines=atoi(buf);
10010 else
10011 {
10012 pclose(fp);
10013 fprintf(stderr,"No devices are connected \n");
10014 return RETURN_ERR;
10015 }
10016 pclose(fp);
10017
10018 if(lines == 1)
10019 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10020
10021 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10022 {
10023 stats_entry = &tid_stats->tid_array[tid_index];
10024 stats_entry->tid = tid_index;
10025
10026 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);
10027
10028 fp=popen(pipeCmd,"r");
10029 if(fp ==NULL)
10030 {
10031 perror("Failed to read from tid file \n");
10032 return RETURN_ERR;
10033 }
10034 else if(fgets(buf,sizeof(buf),fp) != NULL)
10035 stats_entry->num_msdus = atol(buf);
10036
10037 pclose(fp);
10038 stats_entry->ac = _tid_ac_index_get[tid_index];
10039// TODO:
10040// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10041// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10042 }
10043 return RETURN_OK;
10044#endif
10045}
10046
10047
10048INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10049{
developerd946fd62022-12-08 18:03:28 +080010050 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +080010051 char cmd[128]={0};
10052 char buf[128]={0};
10053 int freq = 0;
10054
10055 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10056
10057 // full mode is used to scan all channels.
10058 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10059 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10060 ieee80211_channel_to_frequency(chan_list[0], &freq);
10061
developerac6f1142022-12-20 19:26:35 +080010062 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010063 return RETURN_ERR;
10064
developer615510b2022-09-27 10:14:35 +080010065 if (freq)
developerd946fd62022-12-08 18:03:28 +080010066 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +080010067 else
developerd946fd62022-12-08 18:03:28 +080010068 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +080010069
10070 _syscmd(cmd, buf, sizeof(buf));
10071 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10072
developer06a01d92022-09-07 16:32:39 +080010073 return RETURN_OK;
10074}
10075
10076
10077INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10078{
10079 // TODO Implement me!
10080 return RETURN_ERR;
10081}
10082
10083INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10084{
10085 // TODO Implement me!
10086 return RETURN_ERR;
10087}
10088
10089INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10090{
10091 // TODO Implement me!
10092 return RETURN_ERR;
10093}
10094
10095INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10096{
10097 // TODO Implement me!
10098 return RETURN_ERR;
10099}
10100
10101INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10102{
10103 // TODO Implement me!
10104 return RETURN_ERR;
10105}
10106
10107INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10108{
10109 // TODO Implement me!
10110 return RETURN_ERR;
10111}
10112
10113INT wifi_steering_eventUnregister(void)
10114{
10115 // TODO Implement me!
10116 return RETURN_ERR;
10117}
10118
10119INT wifi_delApAclDevices(INT apIndex)
10120{
10121#if 0
10122 char cmd[MAX_BUF_SIZE] = {0};
10123 char buf[MAX_BUF_SIZE] = {0};
10124
10125 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010126 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010127 if(_syscmd(cmd,buf,sizeof(buf)))
10128 return RETURN_ERR;
10129#endif
developer9988c232023-03-06 14:57:08 +080010130 char cmd[256]={0};
10131 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010132
developere6aafda2022-09-13 14:59:28 +080010133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010134 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 +080010135 if(_syscmd(cmd, buf, sizeof(buf)))
10136 return RETURN_ERR;
10137 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010138
10139 return RETURN_OK;
10140}
10141
10142#ifdef HAL_NETLINK_IMPL
10143static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10144 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10145 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10146 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10147 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10148 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10149 char mac_addr[20],dev[20];
10150
10151 nla_parse(tb,
10152 NL80211_ATTR_MAX,
10153 genlmsg_attrdata(gnlh, 0),
10154 genlmsg_attrlen(gnlh, 0),
10155 NULL);
10156
10157 if(!tb[NL80211_ATTR_STA_INFO]) {
10158 fprintf(stderr, "sta stats missing!\n");
10159 return NL_SKIP;
10160 }
10161
10162 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10163 fprintf(stderr, "failed to parse nested attributes!\n");
10164 return NL_SKIP;
10165 }
10166 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10167
10168 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10169
10170 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10171 fprintf(stderr, "failed to parse nested rate attributes!");
10172 return NL_SKIP;
10173 }
10174
10175 if(sinfo[NL80211_STA_INFO_TID_STATS])
10176 {
10177 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10178 printf("failed to parse nested stats attributes!");
10179 return NL_SKIP;
10180 }
10181 }
10182
10183 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10184 {
10185 printf("Type is VHT\n");
10186 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10187 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10188
10189 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10190 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10191 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10192 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10193 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10194 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10195 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10196 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10197 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10198 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10199 }
10200 else
10201 {
10202 printf(" OFDM or CCK \n");
10203 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10204 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10205 }
10206
10207 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10208 if(rinfo[NL80211_RATE_INFO_MCS])
10209 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10210 }
10211 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10212 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10213 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10214 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10215
10216 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10217 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10218
10219 if (sinfo[NL80211_STA_INFO_SIGNAL])
10220 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10221 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10222 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10223 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10224 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10225 //rssi_array need to be filled
10226 return NL_SKIP;
10227}
10228#endif
10229
10230INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10231{
10232#ifdef HAL_NETLINK_IMPL
10233 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010234 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010235 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010236 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010237
10238 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10239
10240 if (*output_array_size <= 0)
10241 return RETURN_OK;
10242
developer06a01d92022-09-07 16:32:39 +080010243 nl.id = initSock80211(&nl);
10244
10245 if (nl.id < 0) {
10246 fprintf(stderr, "Error initializing netlink \n");
10247 return 0;
10248 }
10249
10250 struct nl_msg* msg = nlmsg_alloc();
10251
10252 if (!msg) {
10253 fprintf(stderr, "Failed to allocate netlink message.\n");
10254 nlfree(&nl);
10255 return 0;
10256 }
10257
10258 genlmsg_put(msg,
10259 NL_AUTO_PORT,
10260 NL_AUTO_SEQ,
10261 nl.id,
10262 0,
10263 0,
10264 NL80211_CMD_GET_STATION,
10265 0);
10266
10267 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10268 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10269 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10270 nl_send_auto(nl.socket, msg);
10271 nl_recvmsgs(nl.socket, nl.cb);
10272 nlmsg_free(msg);
10273 nlfree(&nl);
10274 return RETURN_OK;
10275#else
10276 //TODO Implement me
10277 return RETURN_OK;
10278#endif
10279}
10280
10281#ifdef HAL_NETLINK_IMPL
10282static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10283 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10284 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10285 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10286 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10287 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10288 char mac_addr[20],dev[20];
10289
10290 nla_parse(tb,
10291 NL80211_ATTR_MAX,
10292 genlmsg_attrdata(gnlh, 0),
10293 genlmsg_attrlen(gnlh, 0),
10294 NULL);
10295
10296 if(!tb[NL80211_ATTR_STA_INFO]) {
10297 fprintf(stderr, "sta stats missing!\n");
10298 return NL_SKIP;
10299 }
10300
10301 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10302 fprintf(stderr, "failed to parse nested attributes!\n");
10303 return NL_SKIP;
10304 }
10305
10306 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10307
10308 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10309
10310 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10311 fprintf(stderr, "failed to parse nested rate attributes!");
10312 return NL_SKIP;
10313 }
10314
10315 if(sinfo[NL80211_STA_INFO_TID_STATS])
10316 {
10317 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10318 printf("failed to parse nested stats attributes!");
10319 return NL_SKIP;
10320 }
10321 }
10322 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10323 {
10324 printf("Type is VHT\n");
10325 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10326 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10327
10328 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10329 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10330 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10331 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10332 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10333 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10334 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10335 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10336 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10337 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10338 }
10339 else
10340 {
10341 printf(" OFDM or CCK \n");
10342 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10343 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10344 }
10345
10346 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10347 if(rinfo[NL80211_RATE_INFO_MCS])
10348 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10349 }
10350
10351 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10352 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10353 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10354 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10355
10356 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10357 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10358 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10359
10360 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10361 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10362
10363 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10364 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10365
10366 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10367 ((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]);
10368
10369 return NL_SKIP;
10370}
10371#endif
10372
10373INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10374{
10375#ifdef HAL_NETLINK_IMPL
10376 Netlink nl;
10377 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010378 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010379 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010380 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010381
10382 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10383
10384 if (*output_array_size <= 0)
10385 return RETURN_OK;
10386
developerd946fd62022-12-08 18:03:28 +080010387 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010388
10389 nl.id = initSock80211(&nl);
10390
10391 if(nl.id < 0) {
10392 fprintf(stderr, "Error initializing netlink \n");
10393 return 0;
10394 }
10395
10396 struct nl_msg* msg = nlmsg_alloc();
10397
10398 if(!msg) {
10399 fprintf(stderr, "Failed to allocate netlink message.\n");
10400 nlfree(&nl);
10401 return 0;
10402 }
10403
10404 genlmsg_put(msg,
10405 NL_AUTO_PORT,
10406 NL_AUTO_SEQ,
10407 nl.id,
10408 0,
10409 0,
10410 NL80211_CMD_GET_STATION,
10411 0);
10412
10413 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10414 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10415 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10416 nl_send_auto(nl.socket, msg);
10417 nl_recvmsgs(nl.socket, nl.cb);
10418 nlmsg_free(msg);
10419 nlfree(&nl);
10420 return RETURN_OK;
10421#else
10422 //TODO Implement me
10423 return RETURN_OK;
10424#endif
10425}
10426
10427INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10428{
10429 // TODO Implement me!
10430 char buf[MAX_BUF_SIZE] = {0};
10431 char config_file[MAX_BUF_SIZE] = {0};
10432
10433 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10434 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10435 *activate = (strncmp("1",buf,1) == 0);
10436
10437 return RETURN_OK;
10438}
10439
10440INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10441{
10442 char config_file[MAX_BUF_SIZE] = {0};
10443 struct params list;
10444
10445 list.name = "rrm_neighbor_report";
10446 list.value = activate?"1":"0";
10447 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10448 wifi_hostapdWrite(config_file, &list, 1);
10449
10450 return RETURN_OK;
10451}
10452
10453INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10454{
10455 char buf[32] = {0};
10456 char config_file[MAX_BUF_SIZE] = {0};
10457
10458 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10459 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10460 *activate = (strncmp("1",buf,1) == 0);
10461
10462 return RETURN_OK;
10463}
10464#undef HAL_NETLINK_IMPL
10465#ifdef HAL_NETLINK_IMPL
10466static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10467 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10468 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10469 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10470 char dev[20];
10471 int freq =0 ;
10472 static int i=0;
10473
10474 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10475
10476 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10477 };
10478
10479 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10480
10481 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10482
10483 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10484 fprintf(stderr, "survey data missing!\n");
10485 return NL_SKIP;
10486 }
10487
10488 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10489 {
10490 fprintf(stderr, "failed to parse nested attributes!\n");
10491 return NL_SKIP;
10492 }
10493
10494
10495 if(out[0].array_size == 1 )
10496 {
10497 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10498 {
10499 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10500 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10501 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10502
10503 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10504 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10505 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10506 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10507 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10508 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10509 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10510 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10511 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10512 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10513 if (sinfo[NL80211_SURVEY_INFO_TIME])
10514 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10515 return NL_STOP;
10516 }
10517 }
10518 else
10519 {
10520 if ( i <= out[0].array_size )
10521 {
10522 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10523 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10524 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10525
10526 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10527 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10528 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10529 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10530 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10531 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10532 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10533 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10534 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10535 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10536 if (sinfo[NL80211_SURVEY_INFO_TIME])
10537 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10538 }
10539 }
10540
10541 i++;
10542 return NL_SKIP;
10543}
10544#endif
10545
10546static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10547{
10548 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10549 FILE *fp;
10550
10551 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10552 {
10553 printf("Creating Frequency-Channel Map\n");
10554 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10555 }
10556 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10557 if((fp = popen(command, "r")))
10558 {
10559 fgets(output, sizeof(output), fp);
10560 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010561 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010562 }
10563
10564 return 0;
10565}
10566
10567static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10568{
10569 int freqMHz = -1;
10570 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010571 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010572
10573 ieee80211_channel_to_frequency(channel, &freqMHz);
10574 if (freqMHz == -1) {
10575 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10576 return -1;
10577 }
10578
developer7930d352022-12-21 17:55:42 +080010579 wifi_GetInterfaceName(radioIndex, interface_name);
10580 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010581 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10582 radioIndex, freqMHz);
10583 return -1;
10584 }
10585
10586 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10587 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10588 return -1;
10589 }
10590
10591 return 0;
10592}
10593
10594static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10595{
10596 const char *ptr = buf;
10597 char *key = NULL;
10598 char *val = NULL;
10599 char line[256] = { '\0' };
10600
10601 while (ptr = get_line_from_str_buf(ptr, line)) {
10602 if (strstr(line, "Frequency")) continue;
10603
10604 key = strtok(line, ":");
10605 val = strtok(NULL, " ");
10606 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10607
10608 if (!strcmp(key, "noise")) {
10609 sscanf(val, "%d", &stats->ch_noise);
10610 if (stats->ch_noise == 0) {
10611 // Workaround for missing noise information.
10612 // Assume -95 for 2.4G and -103 for 5G
10613 if (radioIndex == 0) stats->ch_noise = -95;
10614 if (radioIndex == 1) stats->ch_noise = -103;
10615 }
10616 }
10617 else if (!strcmp(key, "channel active time")) {
10618 sscanf(val, "%llu", &stats->ch_utilization_total);
10619 }
10620 else if (!strcmp(key, "channel busy time")) {
10621 sscanf(val, "%llu", &stats->ch_utilization_busy);
10622 }
10623 else if (!strcmp(key, "channel receive time")) {
10624 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10625 }
10626 else if (!strcmp(key, "channel transmit time")) {
10627 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10628 }
10629 };
10630
10631 return 0;
10632}
10633
10634INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10635{
10636 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10637#ifdef HAL_NETLINK_IMPL
10638 Netlink nl;
10639 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010640 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010641
10642 local[0].array_size = array_size;
10643
developerac6f1142022-12-20 19:26:35 +080010644 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010645 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010646
10647 nl.id = initSock80211(&nl);
10648
10649 if (nl.id < 0) {
10650 fprintf(stderr, "Error initializing netlink \n");
10651 return -1;
10652 }
10653
10654 struct nl_msg* msg = nlmsg_alloc();
10655
10656 if (!msg) {
10657 fprintf(stderr, "Failed to allocate netlink message.\n");
10658 nlfree(&nl);
10659 return -2;
10660 }
10661
10662 genlmsg_put(msg,
10663 NL_AUTO_PORT,
10664 NL_AUTO_SEQ,
10665 nl.id,
10666 0,
10667 NLM_F_DUMP,
10668 NL80211_CMD_GET_SURVEY,
10669 0);
10670
10671 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10672 nl_send_auto(nl.socket, msg);
10673 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10674 nl_recvmsgs(nl.socket, nl.cb);
10675 nlmsg_free(msg);
10676 nlfree(&nl);
10677 //Copying the Values
10678 for(int i=0;i<array_size;i++)
10679 {
10680 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10681 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10682 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10683 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10684 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10685 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10686 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10687 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10688 }
10689#else
10690 ULONG channel = 0;
10691 int i;
10692 int number_of_channels = array_size;
10693 char buf[512];
10694 INT ret;
10695 wifi_channelStats_t tmp_stats;
10696
10697 if (number_of_channels == 0) {
10698 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10699 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10700 return RETURN_ERR;
10701 }
10702 number_of_channels = 1;
10703 input_output_channelStats_array[0].ch_number = channel;
10704 }
10705
10706 for (i = 0; i < number_of_channels; i++) {
10707
10708 input_output_channelStats_array[i].ch_noise = 0;
10709 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10710 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10711 input_output_channelStats_array[i].ch_utilization_busy = 0;
10712 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10713 input_output_channelStats_array[i].ch_utilization_total = 0;
10714
10715 memset(buf, 0, sizeof(buf));
10716 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10717 return RETURN_ERR;
10718 }
10719 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10720 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10721 return RETURN_ERR;
10722 }
10723
10724 // XXX: fake missing 'self' counter which is not available in iw survey output
10725 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10726 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10727
10728 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10729 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10730 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10731 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10732 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10733
10734 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",
10735 __func__,
10736 input_output_channelStats_array[i].ch_number,
10737 input_output_channelStats_array[i].ch_noise,
10738 input_output_channelStats_array[i].ch_utilization_total,
10739 input_output_channelStats_array[i].ch_utilization_busy,
10740 input_output_channelStats_array[i].ch_utilization_busy_rx,
10741 input_output_channelStats_array[i].ch_utilization_busy_tx,
10742 input_output_channelStats_array[i].ch_utilization_busy_self,
10743 input_output_channelStats_array[i].ch_utilization_busy_ext);
10744 }
10745#endif
10746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10747 return RETURN_OK;
10748}
10749#define HAL_NETLINK_IMPL
10750
10751/* Hostapd events */
10752
10753#ifndef container_of
10754#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10755#define container_of(ptr, type, member) \
10756 ((type *)((char *)ptr - offset_of(type, member)))
10757#endif /* container_of */
10758
10759struct ctrl {
10760 char sockpath[128];
10761 char sockdir[128];
10762 char bss[IFNAMSIZ];
10763 char reply[4096];
10764 int ssid_index;
10765 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10766 void (*overrun)(struct ctrl *ctrl);
10767 struct wpa_ctrl *wpa;
10768 unsigned int ovfl;
10769 size_t reply_len;
10770 int initialized;
10771 ev_timer retry;
10772 ev_timer watchdog;
10773 ev_stat stat;
10774 ev_io io;
10775};
10776static wifi_newApAssociatedDevice_callback clients_connect_cb;
10777static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10778static struct ctrl wpa_ctrl[MAX_APS];
10779static int initialized;
10780
10781static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10782{
10783 char cbuf[256] = {};
10784 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10785 struct cmsghdr *cmsg;
10786 unsigned int ovfl = ctrl->ovfl;
10787 unsigned int drop;
10788
10789 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10790 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10791 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10792 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10793
10794 drop = ovfl - ctrl->ovfl;
10795 ctrl->ovfl = ovfl;
10796
10797 return drop;
10798}
10799
10800static void ctrl_close(struct ctrl *ctrl)
10801{
10802 if (ctrl->io.cb)
10803 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10804 if (ctrl->retry.cb)
10805 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10806 if (!ctrl->wpa)
10807 return;
10808
10809 wpa_ctrl_detach(ctrl->wpa);
10810 wpa_ctrl_close(ctrl->wpa);
10811 ctrl->wpa = NULL;
10812 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10813}
10814
10815static void ctrl_process(struct ctrl *ctrl)
10816{
10817 const char *str;
10818 int drops;
10819 int level;
10820 int err;
10821
10822 /* Example events:
10823 *
10824 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10825 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10826 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10827 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10828 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10829 */
10830 if (!(str = index(ctrl->reply, '>')))
10831 return;
10832 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10833 return;
10834
10835 str++;
10836
10837 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10838 if (!(str = index(ctrl->reply, ' ')))
10839 return;
10840 wifi_associated_dev_t sta;
10841 memset(&sta, 0, sizeof(sta));
10842
10843 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10844 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10845 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10846
10847 sta.cli_Active=true;
10848
10849 (clients_connect_cb)(ctrl->ssid_index, &sta);
10850 goto handled;
10851 }
10852
10853 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10854 if (!(str = index(ctrl->reply, ' ')))
10855 return;
10856
10857 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10858 goto handled;
10859 }
10860
10861 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10862 printf("CTRL_WPA: handle TERMINATING event\n");
10863 goto retry;
10864 }
10865
10866 if (strncmp("AP-DISABLED", str, 11) == 0) {
10867 printf("CTRL_WPA: handle AP-DISABLED\n");
10868 goto retry;
10869 }
10870
10871 printf("Event not supported!!\n");
10872
10873handled:
10874
10875 if ((drops = ctrl_get_drops(ctrl))) {
10876 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10877 if (ctrl->overrun)
10878 ctrl->overrun(ctrl);
10879 }
10880
10881 return;
10882
10883retry:
10884 printf("WPA_CTRL: closing\n");
10885 ctrl_close(ctrl);
10886 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10887 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10888}
10889
10890static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10891{
10892 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10893 int err;
10894
10895 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10896 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10897 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10898 ctrl->reply[ctrl->reply_len] = 0;
10899 if (err < 0) {
10900 if (errno == EAGAIN || errno == EWOULDBLOCK)
10901 return;
10902 ctrl_close(ctrl);
10903 ev_timer_again(EV_A_ &ctrl->retry);
10904 return;
10905 }
10906
10907 ctrl_process(ctrl);
10908}
10909
10910static int ctrl_open(struct ctrl *ctrl)
10911{
10912 int fd;
10913
10914 if (ctrl->wpa)
10915 return 0;
10916
10917 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10918 if (!ctrl->wpa)
10919 goto err;
10920
10921 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10922 goto err_close;
10923
10924 fd = wpa_ctrl_get_fd(ctrl->wpa);
10925 if (fd < 0)
10926 goto err_detach;
10927
10928 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10929 goto err_detach;
10930
10931 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10932 ev_io_start(EV_DEFAULT_ &ctrl->io);
10933
10934 return 0;
10935
10936err_detach:
10937 wpa_ctrl_detach(ctrl->wpa);
10938err_close:
10939 wpa_ctrl_close(ctrl->wpa);
10940err:
10941 ctrl->wpa = NULL;
10942 return -1;
10943}
10944
10945static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10946{
10947 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10948
10949 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10950 ctrl_open(ctrl);
10951}
10952
10953static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10954{
10955 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10956
10957 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10958 if (ctrl_open(ctrl) == 0) {
10959 printf("WPA_CTRL: retry successful\n");
10960 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10961 }
10962}
10963
10964int ctrl_enable(struct ctrl *ctrl)
10965{
10966 if (ctrl->wpa)
10967 return 0;
10968
10969 if (!ctrl->stat.cb) {
10970 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10971 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10972 }
10973
10974 if (!ctrl->retry.cb) {
10975 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10976 }
10977
10978 return ctrl_open(ctrl);
10979}
10980
10981static void
10982ctrl_msg_cb(char *buf, size_t len)
10983{
10984 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10985
10986 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10987 ctrl_process(ctrl);
10988}
10989
10990static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10991{
10992 int err;
10993
10994 if (!ctrl->wpa)
10995 return -1;
10996 if (*reply_len < 2)
10997 return -1;
10998
10999 (*reply_len)--;
11000 ctrl->reply_len = sizeof(ctrl->reply);
11001 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11002 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11003 if (err < 0)
11004 return err;
11005
11006 if (ctrl->reply_len > *reply_len)
11007 ctrl->reply_len = *reply_len;
11008
11009 *reply_len = ctrl->reply_len;
11010 memcpy(reply, ctrl->reply, *reply_len);
11011 reply[*reply_len - 1] = 0;
11012 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11013 return 0;
11014}
11015
11016static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11017{
11018 const char *pong = "PONG";
11019 const char *ping = "PING";
11020 char reply[1024];
11021 size_t len = sizeof(reply);
11022 int err;
11023 ULONG s, snum;
11024 INT ret;
11025 BOOL status;
11026
11027 printf("WPA_CTRL: watchdog cb\n");
11028
11029 ret = wifi_getSSIDNumberOfEntries(&snum);
11030 if (ret != RETURN_OK) {
11031 printf("%s: failed to get SSID count", __func__);
11032 return;
11033 }
11034
11035 if (snum > MAX_APS) {
11036 printf("more ssid than supported! %lu\n", snum);
11037 return;
11038 }
11039
11040 for (s = 0; s < snum; s++) {
11041 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080011042 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080011043 continue;
11044 }
11045 if (status == false) continue;
11046
11047 memset(reply, 0, sizeof(reply));
11048 len = sizeof(reply);
11049 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11050 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11051 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11052 continue;
11053
11054 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11055 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080011056 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080011057 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11058 }
11059}
11060
11061static int init_wpa()
11062{
11063 int ret = 0, i = 0;
11064 ULONG s, snum;
11065
11066 ret = wifi_getSSIDNumberOfEntries(&snum);
11067 if (ret != RETURN_OK) {
11068 printf("%s: failed to get SSID count", __func__);
11069 return RETURN_ERR;
11070 }
11071
11072 if (snum > MAX_APS) {
11073 printf("more ssid than supported! %lu\n", snum);
11074 return RETURN_ERR;
11075 }
11076
11077 for (s = 0; s < snum; s++) {
11078 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11079 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11080 wpa_ctrl[s].ssid_index = s;
11081 ctrl_enable(&wpa_ctrl[s]);
11082 }
11083
11084 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11085 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11086
11087 initialized = 1;
11088 printf("WPA_CTRL: initialized\n");
11089
11090 return RETURN_OK;
11091}
11092
11093void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11094{
11095 clients_connect_cb = callback_proc;
11096 if (!initialized)
11097 init_wpa();
11098}
11099
11100void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11101{
11102 clients_disconnect_cb = callback_proc;
11103 if (!initialized)
11104 init_wpa();
11105}
11106
11107INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11108{
11109 // TODO Implement me!
11110 return RETURN_ERR;
11111}
11112
11113INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11114{
11115 // TODO Implement me!
11116 return RETURN_ERR;
11117}
11118
11119INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11120{
11121 int i;
developer4b102122023-02-15 10:53:03 +080011122 int phyId = -1;
11123 char cmd[256] = {0};
11124 char channel_numbers_buf[256] = {0};
11125 char dfs_state_buf[256] = {0};
11126 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011127 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011128 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080011129
developer4b102122023-02-15 10:53:03 +080011130 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011131
developer4b102122023-02-15 10:53:03 +080011132 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11133 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011134
developer4b102122023-02-15 10:53:03 +080011135 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 +080011136
developer4b102122023-02-15 10:53:03 +080011137 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11138 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11139 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011140 }
11141
developer4b102122023-02-15 10:53:03 +080011142 ptr = channel_numbers_buf;
11143 i = 0;
11144 while (ptr = get_line_from_str_buf(ptr, line)) {
11145 if (i >= outputMapSize) {
11146 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11147 return RETURN_ERR;
11148 }
11149 sscanf(line, "%d", &outputMap[i].ch_number);
11150
11151 memset(cmd, 0, sizeof(cmd));
11152 // Below command should fetch string for DFS state (usable, available or unavailable)
11153 // Example line: "DFS state: usable (for 78930 sec)"
11154 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) {
11155 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011156 return RETURN_ERR;
11157 }
11158
developer4b102122023-02-15 10:53:03 +080011159 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11160 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011161 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11162 return RETURN_ERR;
11163 }
11164
developer4b102122023-02-15 10:53:03 +080011165 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011166
developer4b102122023-02-15 10:53:03 +080011167 if (!strcmp(dfs_state_buf, "usable")) {
11168 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11169 } else if (!strcmp(dfs_state_buf, "available")) {
11170 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11171 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11172 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11173 } else {
11174 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011175 }
developer4b102122023-02-15 10:53:03 +080011176 i++;
developer06a01d92022-09-07 16:32:39 +080011177 }
11178
developer4b102122023-02-15 10:53:03 +080011179 return RETURN_OK;
11180
developer06a01d92022-09-07 16:32:39 +080011181 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11182 return RETURN_ERR;
11183}
11184
11185INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11186{
11187 // TODO Implement me!
11188 return RETURN_ERR;
11189}
11190
11191INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11192{
11193 return RETURN_OK;
11194}
11195
11196INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11197{
11198 // TODO Implement me!
11199 return RETURN_ERR;
11200}
11201
11202INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11203{
11204 // TODO API refrence Implementaion is present on RPI hal
11205 return RETURN_ERR;
11206}
11207
developerfeab1d12023-09-27 11:29:38 +080011208
developer06a01d92022-09-07 16:32:39 +080011209INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11210{
developera5005b62022-09-13 15:43:35 +080011211 char cmd[128]={'\0'};
11212 char buf[128]={'\0'};
developerfeab1d12023-09-27 11:29:38 +080011213 int radioIndex = -1;
11214 int phyIndex = -1;
11215 bool enabled = false;
11216 int cur_tx_dbm = 0;
developera5005b62022-09-13 15:43:35 +080011217
11218 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfeab1d12023-09-27 11:29:38 +080011219
developera5005b62022-09-13 15:43:35 +080011220 if(txpwr_pcntg == NULL)
11221 return RETURN_ERR;
11222
developerfeab1d12023-09-27 11:29:38 +080011223 // The API name as getRadioXXX, I think the input index should be radioIndex,
11224 // but current we not change the name, but use it as radioIndex
11225 radioIndex = apIndex;
11226 phyIndex = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +080011227
developera5005b62022-09-13 15:43:35 +080011228 // Get the maximum tx power of the device
developerfeab1d12023-09-27 11:29:38 +080011229 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11230 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011231 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011232 if (strcmp(buf, "enable") == 0)
11233 enabled = true;
developera5005b62022-09-13 15:43:35 +080011234
developerfeab1d12023-09-27 11:29:38 +080011235 if (!enabled) {
11236 *txpwr_pcntg = 100;
11237 return RETURN_OK;
11238 }
11239
developera5005b62022-09-13 15:43:35 +080011240 memset(cmd, 0, sizeof(cmd));
11241 memset(buf, 0, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011242 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11243 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011244 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011245 cur_tx_dbm = strtol(buf, NULL, 10);
developera5005b62022-09-13 15:43:35 +080011246
developerfeab1d12023-09-27 11:29:38 +080011247 switch (cur_tx_dbm) {
11248 case 0:
11249 *txpwr_pcntg = 100; // range 91-100
developera5005b62022-09-13 15:43:35 +080011250 break;
developerfeab1d12023-09-27 11:29:38 +080011251 case 1:
11252 *txpwr_pcntg = 75; // range 61-90
11253 break;
11254 case 3:
11255 *txpwr_pcntg = 50; // range 31-60
11256 break;
11257 case 6:
11258 *txpwr_pcntg = 25; // range 16-30
11259 break;
11260 case 9:
11261 *txpwr_pcntg = 12; // range 10-15
11262 break;
11263 case 12:
11264 *txpwr_pcntg = 6; // range 1-9
11265 break;
11266 default:
11267 *txpwr_pcntg = 100; // 0
developera5005b62022-09-13 15:43:35 +080011268 }
developerfeab1d12023-09-27 11:29:38 +080011269
developer06a01d92022-09-07 16:32:39 +080011270 return RETURN_OK;
11271}
11272
11273INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11274{
developer58599c22022-09-13 16:40:34 +080011275 // TODO precac feature.
11276 struct params params = {0};
11277 char config_file[128] = {0};
11278
11279 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11280
11281 params.name = "enable_background_radar";
11282 params.value = enable?"1":"0";
11283 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11284 wifi_hostapdWrite(config_file, &params, 1);
11285 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11286
11287 /* TODO precac feature */
11288
11289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11290 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011291}
11292
11293INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11294{
developer58599c22022-09-13 16:40:34 +080011295 char config_file[128] = {0};
11296 char buf[64] = {0};
11297
11298 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11299 if (NULL == enable || NULL == precac)
11300 return RETURN_ERR;
11301
11302 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11303 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011304 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011305 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011306 *precac = true;
11307 } else {
developer58599c22022-09-13 16:40:34 +080011308 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011309 *precac = false;
11310 }
developer58599c22022-09-13 16:40:34 +080011311
11312 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11313 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011314}
11315
11316INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11317{
developer58599c22022-09-13 16:40:34 +080011318 *supported = TRUE;
11319 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011320}
11321
developera7149722023-01-11 11:36:21 +080011322bool check_is_hemu_vendor_new_patch() {
11323 char cmd[128] = {0};
11324 char buf[128] = {0};
11325
11326 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11327 _syscmd(cmd, buf, sizeof(buf));
11328
11329 if (strlen(buf) > 0)
11330 return FALSE;
11331 else
11332 return TRUE;
11333}
11334
developer3e6b1692022-09-30 18:04:05 +080011335INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11336{
11337 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11338 struct params params = {0};
11339 char config_file[64] = {0};
11340 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011341 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011342 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011343 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011344 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11345
developera7149722023-01-11 11:36:21 +080011346 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011347
11348 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11349 set_mu_type &= ~0x05; // unset bit 0, 2
11350 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11351 set_mu_type |= 0x01;
11352 set_mu_type &= ~0x04;
11353 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11354 set_mu_type &= ~0x01;
11355 set_mu_type |= 0x04;
11356 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11357 set_mu_type |= 0x05; // set bit 0, 2
11358 }
11359
developera7149722023-01-11 11:36:21 +080011360 new_vendor_patch = check_is_hemu_vendor_new_patch();
11361 if (new_vendor_patch)
11362 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11363 else
11364 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11365
11366 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011367 sprintf(buf, "%u", set_mu_type);
11368 params.value = buf;
11369 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11370 wifi_hostapdWrite(config_file, &params, 1);
11371 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011372 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011373
11374 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11375 return RETURN_OK;
11376}
11377
11378INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11379{
11380 struct params params={0};
11381 char config_file[64] = {0};
11382 char buf[64] = {0};
11383 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011384 bool new_vendor_patch = FALSE;
11385 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011386
11387 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11388
11389 if (mu_type == NULL)
11390 return RETURN_ERR;
11391
developera7149722023-01-11 11:36:21 +080011392 new_vendor_patch = check_is_hemu_vendor_new_patch();
11393
11394 if (new_vendor_patch)
11395 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11396 else
11397 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11398
developer3e6b1692022-09-30 18:04:05 +080011399 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011400 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011401 get_mu_type = strtol(buf, NULL, 10);
11402
11403 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11404 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11405 else if (get_mu_type & 0x04)
11406 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11407 else if (get_mu_type & 0x01)
11408 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11409 else
11410 *mu_type = WIFI_DL_MU_TYPE_NONE;
11411
11412 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11413 return RETURN_OK;
11414}
11415
11416INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11417{
11418 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11419 struct params params={0};
11420 char config_file[64] = {0};
11421 char buf[64] = {0};
11422 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011423 bool new_vendor_patch = FALSE;
11424 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011425 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11426
developera7149722023-01-11 11:36:21 +080011427 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011428
11429 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11430 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11431 set_mu_type &= ~0x0a;
11432 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11433 set_mu_type |= 0x02;
11434 set_mu_type &= ~0x08;
11435 }
11436
developera7149722023-01-11 11:36:21 +080011437 new_vendor_patch = check_is_hemu_vendor_new_patch();
11438
11439 if (new_vendor_patch)
11440 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11441 else
11442 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11443
11444 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011445 sprintf(buf, "%u", set_mu_type);
11446 params.value = buf;
11447 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11448 wifi_hostapdWrite(config_file, &params, 1);
11449 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011450 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011451
11452 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11453 return RETURN_OK;
11454}
11455
11456INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11457{
11458 struct params params={0};
11459 char config_file[64] = {0};
11460 char buf[64] = {0};
11461 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011462 bool new_vendor_patch = FALSE;
11463 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011464
11465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11466
developera7149722023-01-11 11:36:21 +080011467 new_vendor_patch = check_is_hemu_vendor_new_patch();
11468
11469 if (new_vendor_patch)
11470 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11471 else
11472 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11473
developer3e6b1692022-09-30 18:04:05 +080011474 if (mu_type == NULL)
11475 return RETURN_ERR;
11476
11477 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011478 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011479
11480 get_mu_type = strtol(buf, NULL, 10);
11481 if (get_mu_type & 0x02)
11482 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11483 else
11484 *mu_type = WIFI_DL_MU_TYPE_NONE;
11485
11486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11487 return RETURN_OK;
11488}
11489
11490
developer454b9462022-09-13 15:29:16 +080011491INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11492{
11493 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011494 char buf[256] = {0};
11495 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011496 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011497 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011498 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011499 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011500
11501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11502
developer254882b2022-09-30 17:12:31 +080011503 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011504 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11505 return RETURN_ERR;
11506 }
developer454b9462022-09-13 15:29:16 +080011507
developer254882b2022-09-30 17:12:31 +080011508 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011509 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011510
developer254882b2022-09-30 17:12:31 +080011511 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11512 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011513 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011514 _syscmd(cmd, buf, sizeof(buf));
11515 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11516 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11517 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011518 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 +080011519 _syscmd(cmd, buf, sizeof(buf));
11520 }
11521 if (band == band_5) {
11522 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11523 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011524 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 +080011525 _syscmd(cmd, buf, sizeof(buf));
11526 }
11527 }
11528 }
11529 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011530
developer254882b2022-09-30 17:12:31 +080011531 if (guard_interval == wifi_guard_interval_400)
11532 strcpy(GI, "0.4");
11533 else if (guard_interval == wifi_guard_interval_800)
11534 strcpy(GI, "0.8");
11535 else if (guard_interval == wifi_guard_interval_1600)
11536 strcpy(GI, "1.6");
11537 else if (guard_interval == wifi_guard_interval_3200)
11538 strcpy(GI, "3.2");
11539 else if (guard_interval == wifi_guard_interval_auto)
11540 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011541 // Record GI for get GI function
11542 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11543 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011544 if (f == NULL)
11545 return RETURN_ERR;
11546 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011547 fclose(f);
11548 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11549 return RETURN_OK;
11550}
11551
11552INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11553{
11554 char buf[32] = {0};
11555 char cmd[64] = {0};
11556
11557 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11558
11559 if (guard_interval == NULL)
11560 return RETURN_ERR;
11561
developer7c4cd202023-03-01 10:56:29 +080011562 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011563 _syscmd(cmd, buf, sizeof(buf));
11564
11565 if (strncmp(buf, "0.4", 3) == 0)
11566 *guard_interval = wifi_guard_interval_400;
11567 else if (strncmp(buf, "0.8", 3) == 0)
11568 *guard_interval = wifi_guard_interval_800;
11569 else if (strncmp(buf, "1.6", 3) == 0)
11570 *guard_interval = wifi_guard_interval_1600;
11571 else if (strncmp(buf, "3.2", 3) == 0)
11572 *guard_interval = wifi_guard_interval_3200;
11573 else
11574 *guard_interval = wifi_guard_interval_auto;
11575
11576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11577 return RETURN_OK;
11578}
11579
developer3cc61d12022-09-13 16:36:05 +080011580INT wifi_setBSSColor(INT radio_index, UCHAR color)
11581{
11582 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11583 struct params params = {0};
11584 char config_file[128] = {0};
11585 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011586 UCHAR *color_list;
11587 int color_num = 0;
11588 int maxNumberColors = 64;
11589 BOOL color_is_aval = FALSE;
11590
developerbf0b9dc2023-07-06 14:30:54 +080011591 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011592 return RETURN_ERR;
11593
developer517f3be2023-05-08 10:02:39 +080011594 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11595 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11596 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011597 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011598 }
developer2acb9632023-03-14 14:58:31 +080011599
11600 for (int i = 0; i < color_num; i++) {
11601 if (color_list[i] == color) {
11602 color_is_aval = TRUE;
11603 break;
11604 }
11605 }
11606 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011607 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011608 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11609 return RETURN_ERR;
11610 }
developer3cc61d12022-09-13 16:36:05 +080011611
11612 params.name = "he_bss_color";
11613 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11614 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011615 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011616 wifi_hostapdWrite(config_file, &params, 1);
11617 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011618 wifi_reloadAp(radio_index);
11619
developer517f3be2023-05-08 10:02:39 +080011620 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011621 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11622 return RETURN_OK;
11623}
11624
11625INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11626{
developer3cc61d12022-09-13 16:36:05 +080011627 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011628 char cmd[128] = {0};
11629 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011630
developer3cc61d12022-09-13 16:36:05 +080011631 if (NULL == color)
11632 return RETURN_ERR;
11633
developer2acb9632023-03-14 14:58:31 +080011634 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11635 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011636
developer2acb9632023-03-14 14:58:31 +080011637 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11638 _syscmd(cmd, buf, sizeof(buf));
11639 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011640
developer2acb9632023-03-14 14:58:31 +080011641 return RETURN_OK;
11642}
11643
11644INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11645{
11646 char buf[64] = {0};
11647 char cmd[128] = {0};
11648 char interface_name[16] = {0};
11649 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011650
developer2acb9632023-03-14 14:58:31 +080011651 if (NULL == colorList || NULL == numColorReturned)
11652 return RETURN_ERR;
11653
11654 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11655 return RETURN_ERR;
11656
11657 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11658 _syscmd(cmd, buf, sizeof(buf));
11659 color_bitmap = strtoull(buf, NULL, 16);
11660
11661 *numColorReturned = 0;
11662 for (int i = 0; i < maxNumberColors; i++) {
11663 if (color_bitmap & 1) {
11664 colorList[*numColorReturned] = i;
11665 (*numColorReturned) += 1;
11666 }
11667 color_bitmap >>= 1;
11668 }
developer3cc61d12022-09-13 16:36:05 +080011669 return RETURN_OK;
11670}
11671
developer06a01d92022-09-07 16:32:39 +080011672/* multi-psk support */
11673INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11674{
11675 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011676 char interface_name[16] = {0};
11677
developerac6f1142022-12-20 19:26:35 +080011678 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011679 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011680
developerd946fd62022-12-08 18:03:28 +080011681 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11682 interface_name,
developer06a01d92022-09-07 16:32:39 +080011683 mac[0],
11684 mac[1],
11685 mac[2],
11686 mac[3],
11687 mac[4],
11688 mac[5]
11689 );
11690 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11691 _syscmd(cmd, key->wifi_keyId, 64);
11692
11693
11694 return RETURN_OK;
11695}
11696
11697INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11698{
developerd946fd62022-12-08 18:03:28 +080011699 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011700 FILE *fd = NULL;
11701 char fname[100];
11702 char cmd[128] = {0};
11703 char out[64] = {0};
11704 wifi_key_multi_psk_t * key = NULL;
11705 if(keysNumber < 0)
11706 return RETURN_ERR;
11707
developer431128d2022-12-16 15:30:41 +080011708 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011709 fd = fopen(fname, "w");
11710 if (!fd) {
11711 return RETURN_ERR;
11712 }
11713 key= (wifi_key_multi_psk_t *) keys;
11714 for(int i=0; i<keysNumber; ++i, key++) {
11715 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11716 }
11717 fclose(fd);
11718
11719 //reload file
developerac6f1142022-12-20 19:26:35 +080011720 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011721 return RETURN_ERR;
11722 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011723 _syscmd(cmd, out, 64);
11724 return RETURN_OK;
11725}
11726
11727INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11728{
11729 FILE *fd = NULL;
11730 char fname[100];
11731 char * line = NULL;
11732 char * pos = NULL;
11733 size_t len = 0;
11734 ssize_t read = 0;
11735 INT ret = RETURN_OK;
11736 wifi_key_multi_psk_t *keys_it = NULL;
11737
11738 if (keysNumber < 1) {
11739 return RETURN_ERR;
11740 }
11741
developer431128d2022-12-16 15:30:41 +080011742 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011743 fd = fopen(fname, "r");
11744 if (!fd) {
11745 return RETURN_ERR;
11746 }
11747
11748 if (keys == NULL) {
11749 ret = RETURN_ERR;
11750 goto close;
11751 }
11752
11753 keys_it = keys;
11754 while ((read = getline(&line, &len, fd)) != -1) {
11755 //Strip trailing new line if present
11756 if (read > 0 && line[read-1] == '\n') {
11757 line[read-1] = '\0';
11758 }
11759
11760 if(strcmp(line,"keyid=")) {
11761 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11762 if (!(pos = index(line, ' '))) {
11763 ret = RETURN_ERR;
11764 goto close;
11765 }
11766 pos++;
11767 //Here should be 00:00:00:00:00:00
11768 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11769 printf("Not supported MAC: %s\n", pos);
11770 }
11771 if (!(pos = index(pos, ' '))) {
11772 ret = RETURN_ERR;
11773 goto close;
11774 }
11775 pos++;
11776
11777 //The rest is PSK
11778 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11779 keys_it++;
11780
11781 if(--keysNumber <= 0)
11782 break;
11783 }
11784 }
11785
11786close:
11787 free(line);
11788 fclose(fd);
11789 return ret;
11790}
11791/* end of multi-psk support */
11792
11793INT wifi_setNeighborReports(UINT apIndex,
11794 UINT numNeighborReports,
11795 wifi_NeighborReport_t *neighborReports)
11796{
11797 char cmd[256] = { 0 };
11798 char hex_bssid[13] = { 0 };
11799 char bssid[18] = { 0 };
11800 char nr[256] = { 0 };
11801 char ssid[256];
11802 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011803 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011804 INT ret;
11805
11806 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011807 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011808 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011809 return RETURN_ERR;
11810 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 +080011811 system(cmd);
11812
11813 for(unsigned int i = 0; i < numNeighborReports; i++)
11814 {
11815 memset(ssid, 0, sizeof(ssid));
11816 ret = wifi_getSSIDName(apIndex, ssid);
11817 if (ret != RETURN_OK)
11818 return RETURN_ERR;
11819
11820 memset(hex_ssid, 0, sizeof(hex_ssid));
11821 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11822 sprintf(hex_ssid + k,"%02x", ssid[j]);
11823
11824 snprintf(hex_bssid, sizeof(hex_bssid),
11825 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11826 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11827 snprintf(bssid, sizeof(bssid),
11828 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11829 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11830
11831 snprintf(nr, sizeof(nr),
11832 "%s" // bssid
11833 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11834 "%02hhx" // operclass
11835 "%02hhx" // channel
11836 "%02hhx", // phy_mode
11837 hex_bssid,
11838 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11839 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11840 neighborReports[i].opClass,
11841 neighborReports[i].channel,
11842 neighborReports[i].phyTable);
11843
11844 snprintf(cmd, sizeof(cmd),
11845 "hostapd_cli set_neighbor "
11846 "%s " // bssid
11847 "ssid=%s " // ssid
11848 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011849 "-i %s",
11850 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011851
11852 if (WEXITSTATUS(system(cmd)) != 0)
11853 {
11854 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11855 }
11856 }
11857
11858 return RETURN_OK;
11859}
11860
11861INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11862{
11863 return RETURN_OK;
11864}
11865
11866#ifdef _WIFI_HAL_TEST_
11867int main(int argc,char **argv)
11868{
11869 int index;
11870 INT ret=0;
11871 char buf[1024]="";
11872
11873 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11874 if(argc<3)
11875 {
11876 if(argc==2)
11877 {
11878 if(!strcmp(argv[1], "init"))
11879 return wifi_init();
11880 if(!strcmp(argv[1], "reset"))
11881 return wifi_reset();
11882 if(!strcmp(argv[1], "wifi_getHalVersion"))
11883 {
11884 char buffer[64];
11885 if(wifi_getHalVersion(buffer)==RETURN_OK)
11886 printf("Version: %s\n", buffer);
11887 else
11888 printf("Error in wifi_getHalVersion\n");
11889 return RETURN_OK;
11890 }
11891 }
11892 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11893 exit(-1);
11894 }
11895
11896 index = atoi(argv[2]);
11897 if(strstr(argv[1], "wifi_getApName")!=NULL)
11898 {
11899 wifi_getApName(index,buf);
11900 printf("Ap name is %s \n",buf);
11901 return 0;
11902 }
11903 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11904 {
11905 BOOL b = FALSE;
11906 BOOL *output_bool = &b;
11907 wifi_getRadioAutoChannelEnable(index,output_bool);
11908 printf("Channel enabled = %d \n",b);
11909 return 0;
11910 }
11911 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11912 {
11913 wifi_getApWpaEncryptionMode(index,buf);
11914 printf("encryption enabled = %s\n",buf);
11915 return 0;
11916 }
11917 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11918 {
11919 BOOL b = FALSE;
11920 BOOL *output_bool = &b;
11921 wifi_getApSsidAdvertisementEnable(index,output_bool);
11922 printf("advertisment enabled = %d\n",b);
11923 return 0;
11924 }
11925 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11926 {
11927 if(argc <= 3 )
11928 {
11929 printf("Insufficient arguments \n");
11930 exit(-1);
11931 }
11932
11933 char sta[20] = {'\0'};
11934 ULLONG handle= 0;
11935 strcpy(sta,argv[3]);
11936 mac_address_t st;
11937 mac_addr_aton(st,sta);
11938
11939 wifi_associated_dev_tid_stats_t tid_stats;
11940 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11941 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11942 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);
11943 }
11944
11945 if(strstr(argv[1], "getApEnable")!=NULL) {
11946 BOOL enable;
11947 ret=wifi_getApEnable(index, &enable);
11948 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11949 }
11950 else if(strstr(argv[1], "setApEnable")!=NULL) {
11951 BOOL enable = atoi(argv[3]);
11952 ret=wifi_setApEnable(index, enable);
11953 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11954 }
11955 else if(strstr(argv[1], "getApStatus")!=NULL) {
11956 char status[64];
11957 ret=wifi_getApStatus(index, status);
11958 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11959 }
11960 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11961 {
11962 wifi_getSSIDNameStatus(index,buf);
11963 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11964 return 0;
11965 }
11966 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11967 wifi_ssidTrafficStats2_t stats={0};
11968 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11969 printf("%s %d: returns %d\n", argv[1], index, ret);
11970 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11971 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11972 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11973 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11974 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11975 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11976 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11977 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11978 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11979 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11980 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11981 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11982 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11983 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11984 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11985 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11986 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11987 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11988 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11989 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11990 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11991 }
11992 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11993 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11994 UINT array_size=0;
11995 UINT i=0;
11996 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11997 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11998 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11999 printf(" neighbor %d:\n", i);
12000 printf(" ap_SSID =%s\n", pt->ap_SSID);
12001 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
12002 printf(" ap_Mode =%s\n", pt->ap_Mode);
12003 printf(" ap_Channel =%d\n", pt->ap_Channel);
12004 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
12005 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12006 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
12007 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
12008 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
12009 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
12010 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12011 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
12012 printf(" ap_Noise =%d\n", pt->ap_Noise);
12013 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
12014 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
12015 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
12016 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
12017 }
12018 if(neighbor_ap_array)
12019 free(neighbor_ap_array); //make sure to free the list
12020 }
12021 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
12022 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
12023 UINT array_size=0;
12024 UINT i=0;
12025 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
12026 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12027 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
12028 printf(" associated_dev %d:\n", i);
12029 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
12030 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
12031 printf(" cli_SNR =%d\n", pt->cli_SNR);
12032 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
12033 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
12034 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
12035 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
12036 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
12037 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
12038 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
12039 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
12040 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
12041 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
12042 }
12043 if(associated_dev_array)
12044 free(associated_dev_array); //make sure to free the list
12045 }
12046
12047 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12048 {
12049#define MAX_ARRAY_SIZE 64
12050 int i, array_size;
12051 char *p, *ch_str;
12052 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12053
12054 if(argc != 5)
12055 {
12056 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12057 exit(-1);
12058 }
12059 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12060
12061 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12062 {
12063 strtok_r(ch_str, ",", &p);
12064 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12065 }
12066 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12067 if(!array_size)
12068 array_size=1;//Need to print current channel statistics
12069 for(i=0; i<array_size; i++)
12070 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12071 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12072 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12073 input_output_channelStats_array[i].ch_number,\
12074 input_output_channelStats_array[i].ch_noise,\
12075 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12076 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12077 input_output_channelStats_array[i].ch_utilization_busy,\
12078 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12079 input_output_channelStats_array[i].ch_utilization_total);
12080 }
12081
12082 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12083 {
12084 if(argc <= 3 )
12085 {
12086 printf("Insufficient arguments \n");
12087 exit(-1);
12088 }
12089 char mac_addr[20] = {'\0'};
12090 wifi_device_t output_struct;
12091 int dev_index = atoi(argv[3]);
12092
12093 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12094 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12095 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);
12096 }
12097
12098 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12099 {
12100 if (argc <= 3)
12101 {
12102 printf("Insufficient arguments\n");
12103 exit(-1);
12104 }
12105 char args[256];
12106 wifi_NeighborReport_t *neighborReports;
12107
12108 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12109 if (!neighborReports)
12110 {
12111 printf("Failed to allocate memory");
12112 exit(-1);
12113 }
12114
12115 for (int i = 3; i < argc; ++i)
12116 {
12117 char *val;
12118 int j = 0;
12119 memset(args, 0, sizeof(args));
12120 strncpy(args, argv[i], sizeof(args));
12121 val = strtok(args, ";");
12122 while (val != NULL)
12123 {
12124 if (j == 0)
12125 {
12126 mac_addr_aton(neighborReports[i - 3].bssid, val);
12127 } else if (j == 1)
12128 {
12129 neighborReports[i - 3].info = strtol(val, NULL, 16);
12130 } else if (j == 2)
12131 {
12132 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12133 } else if (j == 3)
12134 {
12135 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12136 } else if (j == 4)
12137 {
12138 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12139 } else {
12140 printf("Insufficient arguments]n\n");
12141 exit(-1);
12142 }
12143 val = strtok(NULL, ";");
12144 j++;
12145 }
12146 }
12147
12148 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12149 if (ret != RETURN_OK)
12150 {
12151 printf("wifi_setNeighborReports ret = %d", ret);
12152 exit(-1);
12153 }
12154 }
12155 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12156 {
12157 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12158 printf("%s.\n", buf);
12159 else
12160 printf("Error returned\n");
12161 }
12162 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12163 {
12164 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12165 printf("%s.\n", buf);
12166 else
12167 printf("Error returned\n");
12168 }
12169 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12170 {
12171 if (argc <= 2)
12172 {
12173 printf("Insufficient arguments\n");
12174 exit(-1);
12175 }
12176 char buf[64]= {'\0'};
12177 wifi_getRadioOperatingChannelBandwidth(index,buf);
12178 printf("Current bandwidth is %s \n",buf);
12179 return 0;
12180 }
12181 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12182 {
12183 if (argc <= 5)
12184 {
12185 printf("Insufficient arguments\n");
12186 exit(-1);
12187 }
12188 UINT channel = atoi(argv[3]);
12189 UINT width = atoi(argv[4]);
12190 UINT beacon = atoi(argv[5]);
12191 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12192 printf("Result = %d", ret);
12193 }
12194
12195 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12196 return 0;
12197}
12198
12199#endif
12200
12201#ifdef WIFI_HAL_VERSION_3
12202
developer1e5aa162022-09-13 16:06:24 +080012203INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12204{
12205 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12206 if (bitMap & WIFI_BITRATE_1MBPS)
12207 strcat(BasicRate, "1,");
12208 if (bitMap & WIFI_BITRATE_2MBPS)
12209 strcat(BasicRate, "2,");
12210 if (bitMap & WIFI_BITRATE_5_5MBPS)
12211 strcat(BasicRate, "5.5,");
12212 if (bitMap & WIFI_BITRATE_6MBPS)
12213 strcat(BasicRate, "6,");
12214 if (bitMap & WIFI_BITRATE_9MBPS)
12215 strcat(BasicRate, "9,");
12216 if (bitMap & WIFI_BITRATE_11MBPS)
12217 strcat(BasicRate, "11,");
12218 if (bitMap & WIFI_BITRATE_12MBPS)
12219 strcat(BasicRate, "12,");
12220 if (bitMap & WIFI_BITRATE_18MBPS)
12221 strcat(BasicRate, "18,");
12222 if (bitMap & WIFI_BITRATE_24MBPS)
12223 strcat(BasicRate, "24,");
12224 if (bitMap & WIFI_BITRATE_36MBPS)
12225 strcat(BasicRate, "36,");
12226 if (bitMap & WIFI_BITRATE_48MBPS)
12227 strcat(BasicRate, "48,");
12228 if (bitMap & WIFI_BITRATE_54MBPS)
12229 strcat(BasicRate, "54,");
12230 if (strlen(BasicRate) != 0) // remove last comma
12231 BasicRate[strlen(BasicRate) - 1] = '\0';
12232 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12233 return RETURN_OK;
12234}
12235
12236INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12237{
12238 UINT BitMap = 0;
12239 char *rate;
12240
12241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12242 rate = strtok(BasicRatesList, ",");
12243 while(rate != NULL)
12244 {
12245 if (strcmp(rate, "1") == 0)
12246 BitMap |= WIFI_BITRATE_1MBPS;
12247 else if (strcmp(rate, "2") == 0)
12248 BitMap |= WIFI_BITRATE_2MBPS;
12249 else if (strcmp(rate, "5.5") == 0)
12250 BitMap |= WIFI_BITRATE_5_5MBPS;
12251 else if (strcmp(rate, "6") == 0)
12252 BitMap |= WIFI_BITRATE_6MBPS;
12253 else if (strcmp(rate, "9") == 0)
12254 BitMap |= WIFI_BITRATE_9MBPS;
12255 else if (strcmp(rate, "11") == 0)
12256 BitMap |= WIFI_BITRATE_11MBPS;
12257 else if (strcmp(rate, "12") == 0)
12258 BitMap |= WIFI_BITRATE_12MBPS;
12259 else if (strcmp(rate, "18") == 0)
12260 BitMap |= WIFI_BITRATE_18MBPS;
12261 else if (strcmp(rate, "24") == 0)
12262 BitMap |= WIFI_BITRATE_24MBPS;
12263 else if (strcmp(rate, "36") == 0)
12264 BitMap |= WIFI_BITRATE_36MBPS;
12265 else if (strcmp(rate, "48") == 0)
12266 BitMap |= WIFI_BITRATE_48MBPS;
12267 else if (strcmp(rate, "54") == 0)
12268 BitMap |= WIFI_BITRATE_54MBPS;
12269 rate = strtok(NULL, ",");
12270 }
12271 *basicRateBitMap = BitMap;
12272 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12273 return RETURN_OK;
12274}
12275
developer7c4cd202023-03-01 10:56:29 +080012276INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12277{
12278 int center_channel = 0;
12279 char central_channel_str[16] = {0};
12280 char config_file[32] = {0};
12281 struct params param = {0};
12282
12283 center_channel = util_unii_6g_centerfreq("HT320", channel);
12284 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12285 if (channel >= 193)
12286 return RETURN_ERR;
12287 if (channel >= 33) {
12288 if (channel > center_channel)
12289 center_channel += 32;
12290 else
12291 center_channel -= 32;
12292 }
12293 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12294 if (channel <= 29)
12295 return RETURN_ERR;
12296 }
12297 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12298 param.name = "eht_oper_centr_freq_seg0_idx";
12299 param.value = central_channel_str;
12300 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12301 wifi_hostapdWrite(config_file, &param, 1);
12302
12303 return RETURN_OK;
12304}
12305
12306INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12307{
12308 int op_class = 0;
12309 char config_file[32] = {0};
12310 char op_class_str[8] = {0};
12311 struct params param = {0};
12312
12313 if (bandwidth == 20)
12314 op_class = 131;
12315 else if (bandwidth == 40)
12316 op_class = 132;
12317 else if (bandwidth == 80)
12318 op_class = 133;
12319 else if (bandwidth == 160)
12320 op_class = 134;
12321 else if (bandwidth == 320)
12322 op_class = 137;
12323 else
12324 return RETURN_ERR;
12325 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12326 param.name = "op_class";
12327 param.value = op_class_str;
12328 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12329 wifi_hostapdWrite(config_file, &param, 1);
12330 return RETURN_OK;
12331}
12332
12333INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12334{
12335 char config_file[32] = {0};
12336 char buf [16] = {0};
12337
12338 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12339 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12340 return RETURN_ERR; // 6g band should set op_class
12341 *class = (UINT)strtoul(buf, NULL, 10);
12342
12343 return RETURN_OK;
12344}
12345
developer1e5aa162022-09-13 16:06:24 +080012346// 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 +080012347INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12348{
developer1e5aa162022-09-13 16:06:24 +080012349 char buf[128] = {0};
12350 char cmd[128] = {0};
12351 char config_file[64] = {0};
12352 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012353 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012354 wifi_radio_operationParam_t current_param;
12355
12356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12357
12358 multiple_set = TRUE;
12359 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12360 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12361 return RETURN_ERR;
12362 }
12363 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12364 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12365 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12366 return RETURN_ERR;
12367 }
12368 }
developer5884e982022-10-06 10:52:50 +080012369
12370 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12371 bandwidth = 20;
12372 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12373 bandwidth = 40;
12374 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12375 bandwidth = 80;
12376 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12377 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012378 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12379 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012380 if (operationParam->autoChannelEnabled){
12381 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12382 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12383 return RETURN_ERR;
12384 }
12385 }else{
developer1e5aa162022-09-13 16:06:24 +080012386 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12387 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12388 return RETURN_ERR;
12389 }
12390 }
developer5884e982022-10-06 10:52:50 +080012391
developer7c4cd202023-03-01 10:56:29 +080012392 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12393 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12394 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12395 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12396 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12397 return RETURN_ERR;
12398 }
12399 }
12400
12401 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12402 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12403 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12404 return RETURN_ERR;
12405 }
12406 }
12407
developer1e5aa162022-09-13 16:06:24 +080012408 if (current_param.variant != operationParam->variant) {
12409 // Two different definition bit map, so need to check every bit.
12410 if (operationParam->variant & WIFI_80211_VARIANT_A)
12411 set_mode |= WIFI_MODE_A;
12412 if (operationParam->variant & WIFI_80211_VARIANT_B)
12413 set_mode |= WIFI_MODE_B;
12414 if (operationParam->variant & WIFI_80211_VARIANT_G)
12415 set_mode |= WIFI_MODE_G;
12416 if (operationParam->variant & WIFI_80211_VARIANT_N)
12417 set_mode |= WIFI_MODE_N;
12418 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12419 set_mode |= WIFI_MODE_AC;
12420 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12421 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012422 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12423 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012424 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12425 memset(buf, 0, sizeof(buf));
12426 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12427 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12428 return RETURN_ERR;
12429 }
12430 }
12431 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12432 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12433 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12434 return RETURN_ERR;
12435 }
12436 }
12437 if (current_param.beaconInterval != operationParam->beaconInterval) {
12438 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12439 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12440 return RETURN_ERR;
12441 }
12442 }
12443 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12444 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12445 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12446 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12447 return RETURN_ERR;
12448 }
12449 }
12450 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12451 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12452 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12453 return RETURN_ERR;
12454 }
12455 }
12456 if (current_param.guardInterval != operationParam->guardInterval) {
12457 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12458 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12459 return RETURN_ERR;
12460 }
12461 }
12462 if (current_param.transmitPower != operationParam->transmitPower) {
12463 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12464 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12465 return RETURN_ERR;
12466 }
12467 }
12468 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12469 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12470 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12471 return RETURN_ERR;
12472 }
12473 }
12474 if (current_param.obssCoex != operationParam->obssCoex) {
12475 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12476 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12477 return RETURN_ERR;
12478 }
12479 }
12480 if (current_param.stbcEnable != operationParam->stbcEnable) {
12481 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12482 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12483 return RETURN_ERR;
12484 }
12485 }
developer5735d092023-09-19 20:12:26 +080012486 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12487 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12488 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12489 return RETURN_ERR;
12490 }
12491 }
developer1e5aa162022-09-13 16:06:24 +080012492
12493 // if enable is true, then restart the radio
12494 wifi_setRadioEnable(index, FALSE);
12495 if (operationParam->enable == TRUE)
12496 wifi_setRadioEnable(index, TRUE);
12497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12498
developer06a01d92022-09-07 16:32:39 +080012499 return RETURN_OK;
12500}
12501
12502INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12503{
developer1e5aa162022-09-13 16:06:24 +080012504 char band[64] = {0};
12505 char buf[256] = {0};
12506 char config_file[64] = {0};
12507 char cmd[128] = {0};
12508 int ret = RETURN_ERR;
12509 int mode = 0;
12510 ULONG channel = 0;
12511 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012512
12513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12514 printf("Entering %s index = %d\n", __func__, (int)index);
12515
developer1e5aa162022-09-13 16:06:24 +080012516 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12517 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12518 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012519 {
developer1e5aa162022-09-13 16:06:24 +080012520 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012521 return RETURN_ERR;
12522 }
12523 operationParam->enable = enabled;
12524
12525 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012526 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012527 {
developer1e5aa162022-09-13 16:06:24 +080012528 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012529 return RETURN_ERR;
12530 }
12531
12532 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012533 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012534 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012535 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012536 else if (!strcmp(band, "6GHz"))
12537 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012538 else
12539 {
developer1e5aa162022-09-13 16:06:24 +080012540 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012541 band);
12542 }
12543
developer1e5aa162022-09-13 16:06:24 +080012544 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12545 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12546 operationParam->channel = 0;
12547 operationParam->autoChannelEnabled = TRUE;
12548 } else {
12549 operationParam->channel = strtol(buf, NULL, 10);
12550 operationParam->autoChannelEnabled = FALSE;
12551 }
12552
developer06a01d92022-09-07 16:32:39 +080012553 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012554 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12555 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12556 return RETURN_ERR;
12557 }
developer06a01d92022-09-07 16:32:39 +080012558 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12559 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12560 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012561 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012562 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12563 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012564 else
12565 {
developer1e5aa162022-09-13 16:06:24 +080012566 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12567 return false;
developer06a01d92022-09-07 16:32:39 +080012568 }
12569
developer7c4cd202023-03-01 10:56:29 +080012570 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12571 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12572 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12573 return RETURN_ERR;
12574 }
12575 }
12576
developer1e5aa162022-09-13 16:06:24 +080012577 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12578 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12579 return RETURN_ERR;
12580 }
12581 // Two different definition bit map, so need to check every bit.
12582 if (mode & WIFI_MODE_A)
12583 operationParam->variant |= WIFI_80211_VARIANT_A;
12584 if (mode & WIFI_MODE_B)
12585 operationParam->variant |= WIFI_80211_VARIANT_B;
12586 if (mode & WIFI_MODE_G)
12587 operationParam->variant |= WIFI_80211_VARIANT_G;
12588 if (mode & WIFI_MODE_N)
12589 operationParam->variant |= WIFI_80211_VARIANT_N;
12590 if (mode & WIFI_MODE_AC)
12591 operationParam->variant |= WIFI_80211_VARIANT_AC;
12592 if (mode & WIFI_MODE_AX)
12593 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012594 if (mode & WIFI_MODE_BE)
12595 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012596 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12597 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12598 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012599 }
developer1e5aa162022-09-13 16:06:24 +080012600 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12601 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12602 return RETURN_ERR;
12603 }
12604 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12605 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12606 return RETURN_ERR;
12607 }
developer06a01d92022-09-07 16:32:39 +080012608
developer1e5aa162022-09-13 16:06:24 +080012609 memset(buf, 0, sizeof(buf));
12610 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12611 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12612 return RETURN_ERR;
12613 }
12614 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12615
12616 memset(buf, 0, sizeof(buf));
12617 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12618 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12619 return RETURN_ERR;
12620 }
12621 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12622
12623 memset(buf, 0, sizeof(buf));
12624 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12625 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12626
12627 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12628 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12629 return RETURN_ERR;
12630 }
12631 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12632 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12633 return RETURN_ERR;
12634 }
12635
12636 memset(buf, 0, sizeof(buf));
12637 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12638 if (strcmp(buf, "-1") == 0) {
12639 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12640 operationParam->ctsProtection = FALSE;
12641 } else {
12642 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12643 operationParam->ctsProtection = TRUE;
12644 }
12645
12646 memset(buf, 0, sizeof(buf));
12647 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12648 if (strcmp(buf, "0") == 0)
12649 operationParam->obssCoex = FALSE;
12650 else
12651 operationParam->obssCoex = TRUE;
12652
12653 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12654 _syscmd(cmd, buf, sizeof(buf));
12655 if (strlen(buf) != 0)
12656 operationParam->stbcEnable = TRUE;
12657 else
12658 operationParam->stbcEnable = FALSE;
12659
developer5735d092023-09-19 20:12:26 +080012660 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12661 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12662 return RETURN_ERR;
12663 }
developer1e5aa162022-09-13 16:06:24 +080012664
12665 // Below value is hardcoded
12666
12667 operationParam->numSecondaryChannels = 0;
12668 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12669 operationParam->channelSecondary[i] = 0;
12670 }
12671 operationParam->csa_beacon_count = 15;
12672 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012673
12674 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12675 return RETURN_OK;
12676}
12677
12678static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12679{
developerc086fb72022-10-04 10:18:22 +080012680 int max_radio_num = 0;
12681
12682 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012683 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012684 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12685 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012686 }
12687
developerc086fb72022-10-04 10:18:22 +080012688 return (arrayIndex * max_radio_num) + radioIndex;
12689}
developer06a01d92022-09-07 16:32:39 +080012690
developerc086fb72022-10-04 10:18:22 +080012691wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12692 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12693 return WIFI_BITRATE_1MBPS;
12694 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12695 return WIFI_BITRATE_2MBPS;
12696 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12697 return WIFI_BITRATE_5_5MBPS;
12698 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12699 return WIFI_BITRATE_6MBPS;
12700 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12701 return WIFI_BITRATE_9MBPS;
12702 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12703 return WIFI_BITRATE_11MBPS;
12704 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12705 return WIFI_BITRATE_12MBPS;
12706 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12707 return WIFI_BITRATE_18MBPS;
12708 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12709 return WIFI_BITRATE_24MBPS;
12710 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12711 return WIFI_BITRATE_36MBPS;
12712 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12713 return WIFI_BITRATE_48MBPS;
12714 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12715 return WIFI_BITRATE_54MBPS;
12716 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012717}
12718
developer1d57d002022-10-12 18:03:15 +080012719INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12720{
12721 if (beacon == WIFI_BITRATE_1MBPS)
12722 strcpy(beacon_str, "1Mbps");
12723 else if (beacon == WIFI_BITRATE_2MBPS)
12724 strcpy(beacon_str, "2Mbps");
12725 else if (beacon == WIFI_BITRATE_5_5MBPS)
12726 strcpy(beacon_str, "5.5Mbps");
12727 else if (beacon == WIFI_BITRATE_6MBPS)
12728 strcpy(beacon_str, "6Mbps");
12729 else if (beacon == WIFI_BITRATE_9MBPS)
12730 strcpy(beacon_str, "9Mbps");
12731 else if (beacon == WIFI_BITRATE_11MBPS)
12732 strcpy(beacon_str, "11Mbps");
12733 else if (beacon == WIFI_BITRATE_12MBPS)
12734 strcpy(beacon_str, "12Mbps");
12735 else if (beacon == WIFI_BITRATE_18MBPS)
12736 strcpy(beacon_str, "18Mbps");
12737 else if (beacon == WIFI_BITRATE_24MBPS)
12738 strcpy(beacon_str, "24Mbps");
12739 else if (beacon == WIFI_BITRATE_36MBPS)
12740 strcpy(beacon_str, "36Mbps");
12741 else if (beacon == WIFI_BITRATE_48MBPS)
12742 strcpy(beacon_str, "48Mbps");
12743 else if (beacon == WIFI_BITRATE_54MBPS)
12744 strcpy(beacon_str, "54Mbps");
12745 return RETURN_OK;
12746}
12747
developer74ed4192023-09-21 17:15:17 +080012748void checkVapStatus(int apIndex, bool *enable)
12749{
12750 char if_name[16] = {0};
12751 char cmd[128] = {0};
12752 char buf[128] = {0};
12753
12754 *enable = FALSE;
12755 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12756 return;
12757
12758 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12759 _syscmd(cmd, buf, sizeof(buf));
12760 if (strlen(buf) > 0)
12761 *enable = TRUE;
12762 return;
12763}
12764
developer06a01d92022-09-07 16:32:39 +080012765INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12766{
developerc086fb72022-10-04 10:18:22 +080012767 INT mode = 0;
12768 INT ret = -1;
12769 INT output = 0;
12770 int i = 0;
12771 int vap_index = 0;
12772 BOOL enabled = FALSE;
12773 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012774 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012775
developer06a01d92022-09-07 16:32:39 +080012776
12777 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12778 printf("Entering %s index = %d\n", __func__, (int)index);
12779
developera77d84b2023-02-22 16:10:50 +080012780 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012781 {
developerc086fb72022-10-04 10:18:22 +080012782 map->vap_array[i].radio_index = index;
12783
developer06a01d92022-09-07 16:32:39 +080012784 vap_index = array_index_to_vap_index(index, i);
12785 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012786 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012787
developerc086fb72022-10-04 10:18:22 +080012788 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012789
12790 map->vap_array[i].vap_index = vap_index;
12791
12792 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012793 ret = wifi_getApName(vap_index, buf);
12794 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012795 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12796
developerc086fb72022-10-04 10:18:22 +080012797 return RETURN_ERR;
12798 }
12799 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12800
12801 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012802 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012803 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012804 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012805 return RETURN_ERR;
12806 }
12807 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 +080012808
developer74ed4192023-09-21 17:15:17 +080012809 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012810 map->vap_array[i].u.bss_info.enabled = enabled;
12811
developerc086fb72022-10-04 10:18:22 +080012812 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12813 if (ret != RETURN_OK) {
12814 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12815 return RETURN_ERR;
12816 }
developer06a01d92022-09-07 16:32:39 +080012817 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012818
12819 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12820 if (ret != RETURN_OK) {
12821 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12822 return RETURN_ERR;
12823 }
12824 map->vap_array[i].u.bss_info.isolation = enabled;
12825
12826 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12827 if (ret != RETURN_OK) {
12828 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12829 return RETURN_ERR;
12830 }
12831 map->vap_array[i].u.bss_info.bssMaxSta = output;
12832
12833 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12834 if (ret != RETURN_OK) {
12835 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12836 return RETURN_ERR;
12837 }
12838 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012839
developerc086fb72022-10-04 10:18:22 +080012840 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12841 if (ret != RETURN_OK) {
12842 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12843 return RETURN_ERR;
12844 }
12845 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012846
developerc086fb72022-10-04 10:18:22 +080012847 ret = wifi_getApSecurity(vap_index, &security);
12848 if (ret != RETURN_OK) {
12849 printf("%s: wifi_getApSecurity return error\n", __func__);
12850 return RETURN_ERR;
12851 }
12852 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012853
developerc086fb72022-10-04 10:18:22 +080012854 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12855 if (ret != RETURN_OK) {
12856 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12857 return RETURN_ERR;
12858 }
12859 if (mode == 0)
12860 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12861 else
12862 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12863 if (mode == 1)
12864 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12865 else if (mode == 2)
12866 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012867
developerc086fb72022-10-04 10:18:22 +080012868 ret = wifi_getApWmmEnable(vap_index, &enabled);
12869 if (ret != RETURN_OK) {
12870 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12871 return RETURN_ERR;
12872 }
12873 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012874
developerc086fb72022-10-04 10:18:22 +080012875 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12876 if (ret != RETURN_OK) {
12877 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012878 return RETURN_ERR;
12879 }
developerc086fb72022-10-04 10:18:22 +080012880 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012881
12882 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012883 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012884 if (ret != RETURN_OK) {
12885 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12886 return RETURN_ERR;
12887 }
12888 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012889
developerc086fb72022-10-04 10:18:22 +080012890 memset(buf, 0, sizeof(buf));
12891 ret = wifi_getBaseBSSID(vap_index, buf);
12892 if (ret != RETURN_OK) {
12893 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12894 return RETURN_ERR;
12895 }
12896 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12897 &map->vap_array[i].u.bss_info.bssid[0],
12898 &map->vap_array[i].u.bss_info.bssid[1],
12899 &map->vap_array[i].u.bss_info.bssid[2],
12900 &map->vap_array[i].u.bss_info.bssid[3],
12901 &map->vap_array[i].u.bss_info.bssid[4],
12902 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012903 // 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]);
12904
12905 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12906 if (ret != RETURN_OK) {
12907 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12908 return RETURN_ERR;
12909 }
12910 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080012911
12912 ret = wifi_getApWpsEnable(vap_index, &enabled);
12913 if (ret != RETURN_OK) {
12914 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
12915 return RETURN_ERR;
12916 }
12917
12918 map->vap_array[i].u.bss_info.wps.enable = enabled;
12919
developera77d84b2023-02-22 16:10:50 +080012920 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080012921 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012922 }
12923 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12924 return RETURN_OK;
12925}
12926
developer431128d2022-12-16 15:30:41 +080012927
developerd946fd62022-12-08 18:03:28 +080012928static int prepareInterface(UINT apIndex, char *new_interface)
12929{
12930 char cur_interface[16] = {0};
12931 char config_file[128] = {0};
12932 char cmd[128] = {0};
12933 char buf[16] = {0};
12934 int max_radio_num = 0;
12935 int radioIndex = -1;
12936 int phyIndex = -1;
12937
12938 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12939 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12940
12941 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12942 wifi_getMaxRadioNumber(&max_radio_num);
12943 radioIndex = apIndex % max_radio_num;
12944 phyIndex = radio_index_to_phy(radioIndex);
12945 // disable and del old interface, then add new interface
12946 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080012947 if (!(apIndex/max_radio_num)) {
12948 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
12949 _syscmd(cmd, buf, sizeof(buf));
12950 }
developerd946fd62022-12-08 18:03:28 +080012951 }
developer431128d2022-12-16 15:30:41 +080012952 // update the vap status file
12953 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12954 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012955 return RETURN_OK;
12956}
12957
developer06a01d92022-09-07 16:32:39 +080012958INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12959{
developerd946fd62022-12-08 18:03:28 +080012960 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012961 unsigned int i;
12962 wifi_vap_info_t *vap_info = NULL;
12963 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012964 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012965 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012966 char buf[256] = {0};
12967 char cmd[128] = {0};
12968 char config_file[64] = {0};
12969 char bssid[32] = {0};
12970 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012971 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012972
12973 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12974 printf("Entering %s index = %d\n", __func__, (int)index);
12975 for (i = 0; i < map->num_vaps; i++)
12976 {
developer1d57d002022-10-12 18:03:15 +080012977 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012978 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012979
12980 // Check vap status file to enable multiple ap if the system boot.
12981 checkVapStatus(vap_info->vap_index, &enable);
12982 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012983 continue;
developer06a01d92022-09-07 16:32:39 +080012984
developer1d57d002022-10-12 18:03:15 +080012985 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12986
developer431128d2022-12-16 15:30:41 +080012987 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12988 enable = FALSE;
12989
12990 // multi-ap first up need to copy current radio config
12991 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012992 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12993 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012994 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12995 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12996 } else {
12997 // Check whether the interface name is valid or this ap change it.
12998 int apIndex = -1;
12999 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13000 if (apIndex != -1 && apIndex != vap_info->vap_index)
13001 continue;
13002 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080013003 }
developer06a01d92022-09-07 16:32:39 +080013004
developer1d57d002022-10-12 18:03:15 +080013005 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080013006 params[0].name = "interface";
13007 params[0].value = vap_info->vap_name;
13008 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13009 params[1].name = "bssid";
13010 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080013011 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080013012 params[2].name = "wpa_psk_file";
13013 params[2].value = psk_file;
13014
13015 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13016 wifi_hostapdWrite(config_file, params, 3);
13017
13018 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13019 _syscmd(cmd, buf, sizeof(buf));
13020
13021 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13022 if (ret != RETURN_OK) {
13023 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13024 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013025 }
developer1d57d002022-10-12 18:03:15 +080013026
13027 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13028 if (ret != RETURN_OK) {
13029 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13030 return RETURN_ERR;
13031 }
13032
13033 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13034 if (ret != RETURN_OK) {
13035 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13036 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013037 }
13038
developer1d57d002022-10-12 18:03:15 +080013039 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13040 if (ret != RETURN_OK) {
13041 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13042 return RETURN_ERR;
13043 }
developer06a01d92022-09-07 16:32:39 +080013044
developer1d57d002022-10-12 18:03:15 +080013045 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13046 if (ret != RETURN_OK) {
13047 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13048 return RETURN_ERR;
13049 }
developer06a01d92022-09-07 16:32:39 +080013050
developer1d57d002022-10-12 18:03:15 +080013051 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13052 if (ret != RETURN_OK) {
13053 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13054 return RETURN_ERR;
13055 }
13056
developer804c64f2022-10-19 13:54:40 +080013057 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080013058 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080013059 }else {
13060 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080013061 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080013062 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13063 _syscmd(cmd, buf, sizeof(buf));
13064 }else{
developer1d57d002022-10-12 18:03:15 +080013065 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080013066 }
developer1d57d002022-10-12 18:03:15 +080013067 }
13068
13069 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13070 if (ret != RETURN_OK) {
13071 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13072 return RETURN_ERR;
13073 }
13074
13075 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13076 if (ret != RETURN_OK) {
13077 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13078 return RETURN_ERR;
13079 }
13080
13081 memset(buf, 0, sizeof(buf));
13082 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13083 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
13084 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13085 if (ret != RETURN_OK) {
13086 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13087 return RETURN_ERR;
13088 }
13089
developer1d57d002022-10-12 18:03:15 +080013090 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13091 if (ret != RETURN_OK) {
13092 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13093 return RETURN_ERR;
13094 }
13095
13096 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13097 if (ret != RETURN_OK) {
13098 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13099 return RETURN_ERR;
13100 }
developer06a01d92022-09-07 16:32:39 +080013101
developer894affa2023-05-10 18:13:19 +080013102 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
13103 if (ret != RETURN_OK) {
13104 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
13105 return RETURN_ERR;
13106 }
13107
developer2f995fb2023-02-24 10:40:44 +080013108 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080013109 if (vap_info->u.bss_info.enabled == TRUE)
13110 wifi_setApEnable(vap_info->vap_index, TRUE);
13111
developer2f995fb2023-02-24 10:40:44 +080013112 multiple_set = FALSE;
13113
13114 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080013115 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080013116 // The set wps methods function should check whether wps is configured.
13117 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
13118 if (ret != RETURN_OK) {
13119 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
13120 return RETURN_ERR;
13121 }
13122 // wifi_setApWpsConfigMethodsEnabled only write to config.
13123 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13124 if (ret != RETURN_OK) {
13125 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13126 return RETURN_ERR;
13127 }
13128 }
developer2f995fb2023-02-24 10:40:44 +080013129
developer894affa2023-05-10 18:13:19 +080013130 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013131 }
developerfb09ba62023-06-09 17:03:21 +080013132
13133 // IGMP Snooping enable should be placed after all hostapd_reload.
13134 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13135 if (ret != RETURN_OK) {
13136 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13137 return RETURN_ERR;
13138 }
13139
developer06a01d92022-09-07 16:32:39 +080013140 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13141 return RETURN_OK;
13142}
13143
13144int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13145{
13146 char *token, *next;
13147 const char s[2] = ",";
13148 int count =0;
13149
13150 /* get the first token */
13151 token = strtok_r(pchannels, s, &next);
13152
13153 /* walk through other tokens */
13154 while( token != NULL && count < MAX_CHANNELS) {
13155 chlistptr->channels_list[count++] = atoi(token);
13156 token = strtok_r(NULL, s, &next);
13157 }
13158
13159 return count;
13160}
13161
13162static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13163{
13164 INT status;
13165 wifi_channels_list_t *chlistp;
13166 CHAR output_string[64];
13167 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013168 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013169 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013170
13171 if(rcap == NULL)
13172 {
13173 return RETURN_ERR;
13174 }
13175
13176 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013177 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013178
developer1e5aa162022-09-13 16:06:24 +080013179 if (band == band_2_4)
13180 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13181 else if (band == band_5)
13182 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13183 else if (band == band_6)
13184 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013185
13186 chlistp = &(rcap->channel_list[0]);
13187 memset(pchannels, 0, sizeof(pchannels));
13188
13189 /* possible number of radio channels */
13190 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13191 {
13192 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13193 }
13194 /* Number of channels and list*/
13195 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13196
13197 /* autoChannelSupported */
13198 /* always ON with wifi_getRadioAutoChannelSupported */
13199 rcap->autoChannelSupported = TRUE;
13200
13201 /* DCSSupported */
13202 /* always ON with wifi_getRadioDCSSupported */
13203 rcap->DCSSupported = TRUE;
13204
13205 /* zeroDFSSupported - TBD */
13206 rcap->zeroDFSSupported = FALSE;
13207
13208 /* Supported Country List*/
13209 memset(output_string, 0, sizeof(output_string));
13210 status = wifi_getRadioCountryCode(radioIndex, output_string);
13211 if( status != 0 ) {
13212 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13213 return RETURN_ERR;
13214 } else {
13215 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13216 }
13217 if(!strcmp(output_string,"US")){
13218 rcap->countrySupported[0] = wifi_countrycode_US;
13219 rcap->countrySupported[1] = wifi_countrycode_CA;
13220 } else if (!strcmp(output_string,"CA")) {
13221 rcap->countrySupported[0] = wifi_countrycode_CA;
13222 rcap->countrySupported[1] = wifi_countrycode_US;
13223 } else {
13224 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13225 }
13226
13227 rcap->numcountrySupported = 2;
13228
13229 /* csi */
13230 rcap->csi.maxDevices = 8;
13231 rcap->csi.soudingFrameSupported = TRUE;
13232
developer7930d352022-12-21 17:55:42 +080013233 wifi_GetInterfaceName(radioIndex, interface_name);
13234 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013235
13236 /* channelWidth - all supported bandwidths */
13237 int i=0;
13238 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013239
13240 /* mode - all supported variants */
13241 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13242 wifi_getRadioSupportedStandards(radioIndex, output_string);
13243
developer06a01d92022-09-07 16:32:39 +080013244 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13245 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13246 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013247 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013248
developer7c4cd202023-03-01 10:56:29 +080013249 if (strstr(output_string, "n") != NULL)
13250 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13251 if (strstr(output_string, "ax") != NULL)
13252 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13253 if (strstr(output_string, "be") != NULL)
13254 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13255 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013256 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13257 WIFI_CHANNELBANDWIDTH_40MHZ |
13258 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013259 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013260
developer7c4cd202023-03-01 10:56:29 +080013261 if (strstr(output_string, "n") != NULL)
13262 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13263 if (strstr(output_string, "ac") != NULL)
13264 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13265 if (strstr(output_string, "ax") != NULL)
13266 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13267 if (strstr(output_string, "be") != NULL)
13268 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13269 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13270 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13271 WIFI_CHANNELBANDWIDTH_40MHZ |
13272 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013273 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013274
13275 if (strstr(output_string, "be") != NULL) {
13276 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13277 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13278 }
developer06a01d92022-09-07 16:32:39 +080013279 }
developer7c4cd202023-03-01 10:56:29 +080013280
developer06a01d92022-09-07 16:32:39 +080013281 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13282 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13283
13284 /* supportedBitRate - all supported bitrates */
13285 rcap->supportedBitRate[i] = 0;
13286 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13287 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13288 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13289 }
developer1e5aa162022-09-13 16:06:24 +080013290 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013291 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13292 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13293 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13294 }
13295
13296
13297 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13298 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13299 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13300 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13301 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13302 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13303 rcap->cipherSupported = 0;
13304 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13305 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13306
13307 return RETURN_OK;
13308}
13309
13310INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13311{
developer30423732022-12-01 16:17:49 +080013312 INT status = 0, radioIndex = 0;
13313 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013314 int iter = 0;
developer30423732022-12-01 16:17:49 +080013315 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013316 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013317 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013318
13319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13320
13321 memset(cap, 0, sizeof(wifi_hal_capability_t));
13322
13323 /* version */
13324 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13325 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13326
13327 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013328 wifi_getMaxRadioNumber(&max_num_radios);
13329 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013330
13331 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13332 {
13333 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13334 if (status != 0) {
13335 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13336 return RETURN_ERR;
13337 }
13338
13339 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13340 {
developer804c64f2022-10-19 13:54:40 +080013341 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013342 {
13343 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13344 return RETURN_ERR;
13345 }
13346 iface_info = &cap->wifi_prop.interface_map[iter];
13347 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13348 iface_info->rdk_radio_index = radioIndex;
13349 memset(output, 0, sizeof(output));
13350 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13351 {
13352 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13353 }
13354 // TODO: bridge name
13355 // TODO: vlan id
13356 // TODO: primary
13357 iface_info->index = array_index_to_vap_index(radioIndex, j);
13358 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013359 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013360 {
13361 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13362 }
13363 iter++;
13364 }
13365 }
13366
13367 cap->BandSteeringSupported = FALSE;
13368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13369 return RETURN_OK;
13370}
13371
developer9df4e652022-10-11 11:27:38 +080013372INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13373{
13374 struct params h_config={0};
13375 char config_file[64] = {0};
13376
13377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13378
13379 h_config.name = "okc";
13380 h_config.value = okc_enable?"1":"0";
13381
13382 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13383 wifi_hostapdWrite(config_file, &h_config, 1);
13384 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13385
13386 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13387 return RETURN_OK;
13388}
13389
13390INT wifi_setSAEMFP(int ap_index, BOOL enable)
13391{
13392 struct params h_config={0};
13393 char config_file[64] = {0};
13394 char buf[128] = {0};
13395
13396 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13397
13398 h_config.name = "sae_require_mfp";
13399 h_config.value = enable?"1":"0";
13400
13401 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13402 wifi_hostapdWrite(config_file, &h_config, 1);
13403 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13404
13405 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13406 return RETURN_OK;
13407}
13408
13409INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13410{
13411 struct params h_config={0};
13412 char config_file[64] = {0};
13413 char buf[128] = {0};
13414
13415 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13416
13417 h_config.name = "sae_pwe";
13418 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13419 h_config.value = buf;
13420
13421 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13422 wifi_hostapdWrite(config_file, &h_config, 1);
13423 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13424
13425 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13426 return RETURN_OK;
13427}
13428
13429INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13430{
13431 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13432 struct params h_config={0};
13433 char config_file[64] = {0};
13434
13435 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13436
13437 h_config.name = "wpa_disable_eapol_key_retries";
13438 h_config.value = disable_EAPOL_retries?"1":"0";
13439
13440 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13441 wifi_hostapdWrite(config_file, &h_config, 1);
13442 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13443
13444 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13445 return RETURN_OK;
13446}
13447
developer06a01d92022-09-07 16:32:39 +080013448INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13449{
developer587c1b62022-09-27 15:58:59 +080013450 char buf[128] = {0};
13451 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013452 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013453 char password[64] = {0};
13454 char mfp[32] = {0};
13455 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013456 BOOL okc_enable = FALSE;
13457 BOOL sae_MFP = FALSE;
13458 BOOL disable_EAPOL_retries = TRUE;
13459 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013460 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013461 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013462
13463 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13464
13465 multiple_set = TRUE;
13466 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13467 if (security->mode == wifi_security_mode_none) {
13468 strcpy(wpa_mode, "None");
13469 } else if (security->mode == wifi_security_mode_wpa_personal)
13470 strcpy(wpa_mode, "WPA-Personal");
13471 else if (security->mode == wifi_security_mode_wpa2_personal)
13472 strcpy(wpa_mode, "WPA2-Personal");
13473 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13474 strcpy(wpa_mode, "WPA-WPA2-Personal");
13475 else if (security->mode == wifi_security_mode_wpa_enterprise)
13476 strcpy(wpa_mode, "WPA-Enterprise");
13477 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13478 strcpy(wpa_mode, "WPA2-Enterprise");
13479 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13480 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013481 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013482 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013483 okc_enable = TRUE;
13484 sae_MFP = TRUE;
13485 sae_pwe = 2;
13486 disable_EAPOL_retries = FALSE;
13487 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013488 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013489 okc_enable = TRUE;
13490 sae_MFP = TRUE;
13491 sae_pwe = 2;
13492 disable_EAPOL_retries = FALSE;
13493 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013494 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013495 sae_MFP = TRUE;
13496 sae_pwe = 2;
13497 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013498 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013499 strcpy(wpa_mode, "OWE");
13500 sae_MFP = TRUE;
13501 sae_pwe = 2;
13502 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013503 }
13504
13505 band = wifi_index_to_band(ap_index);
13506 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13507 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13508 return RETURN_ERR;
13509 }
developer587c1b62022-09-27 15:58:59 +080013510
13511 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013512 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013513 wifi_setSAEMFP(ap_index, sae_MFP);
13514 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013515 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013516
developerae432c62023-04-24 11:07:20 +080013517 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013518 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) {
13519 int key_len = strlen(security->u.key.key);
13520 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13521 if (key_len == 64) { // set wpa_psk
13522 strncpy(password, security->u.key.key, 64); // 64 characters
13523 password[64] = '\0';
13524 wifi_setApSecurityPreSharedKey(ap_index, password);
13525 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13526 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13527 strncpy(password, security->u.key.key, 63);
13528 password[63] = '\0';
13529 wifi_setApSecurityKeyPassphrase(ap_index, password);
13530 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13531 } else
13532 return RETURN_ERR;
13533 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013534 }
13535 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13536 params.name = "sae_password";
13537 params.value = security->u.key.key;
13538 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013539 } else { // remove sae_password
13540 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13541 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013542 }
13543 }
developer587c1b62022-09-27 15:58:59 +080013544
13545 if (security->mode != wifi_security_mode_none) {
13546 memset(&params, 0, sizeof(params));
13547 params.name = "wpa_pairwise";
13548 if (security->encr == wifi_encryption_tkip)
13549 params.value = "TKIP";
13550 else if (security->encr == wifi_encryption_aes)
13551 params.value = "CCMP";
13552 else if (security->encr == wifi_encryption_aes_tkip)
13553 params.value = "TKIP CCMP";
13554 wifi_hostapdWrite(config_file, &params, 1);
13555 }
13556
13557 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013558 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013559 else if (security->mfp == wifi_mfp_cfg_optional)
13560 strcpy(mfp, "Optional");
13561 else if (security->mfp == wifi_mfp_cfg_required)
13562 strcpy(mfp, "Required");
13563 wifi_setApSecurityMFPConfig(ap_index, mfp);
13564
13565 memset(&params, 0, sizeof(params));
13566 params.name = "transition_disable";
13567 if (security->wpa3_transition_disable == TRUE)
13568 params.value = "0x01";
13569 else
13570 params.value = "0x00";
13571 wifi_hostapdWrite(config_file, &params, 1);
13572
13573 memset(&params, 0, sizeof(params));
13574 params.name = "wpa_group_rekey";
13575 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13576 params.value = buf;
13577 wifi_hostapdWrite(config_file, &params, 1);
13578
13579 memset(&params, 0, sizeof(params));
13580 params.name = "wpa_strict_rekey";
13581 params.value = security->strict_rekey?"1":"0";
13582 wifi_hostapdWrite(config_file, &params, 1);
13583
13584 memset(&params, 0, sizeof(params));
13585 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013586 if (security->eapol_key_retries == 0)
13587 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013588 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13589 params.value = buf;
13590 wifi_hostapdWrite(config_file, &params, 1);
13591
13592 memset(&params, 0, sizeof(params));
13593 params.name = "disable_pmksa_caching";
13594 params.value = security->disable_pmksa_caching?"1":"0";
13595 wifi_hostapdWrite(config_file, &params, 1);
13596
developer23e71282023-01-18 10:25:19 +080013597 if (multiple_set == FALSE) {
13598 wifi_setApEnable(ap_index, FALSE);
13599 wifi_setApEnable(ap_index, TRUE);
13600 }
developer587c1b62022-09-27 15:58:59 +080013601
13602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13603
developer06a01d92022-09-07 16:32:39 +080013604 return RETURN_OK;
13605}
13606
13607INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13608{
developer9df4e652022-10-11 11:27:38 +080013609 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013610 char config_file[128] = {0};
13611 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013612 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013613
13614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13615 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13616 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13617 security->mode = wifi_security_mode_none;
13618 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013619 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013620 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013621 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013622 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013623 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013624 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013625 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013626 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013627 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013628 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013629 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013630 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013631 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013632 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013633 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013634 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013635 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013636 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013637 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013638 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013639 }
13640
13641 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13642 if (security->mode == wifi_security_mode_none)
13643 security->encr = wifi_encryption_none;
13644 else {
13645 if (strcmp(buf, "TKIP") == 0)
13646 security->encr = wifi_encryption_tkip;
13647 else if (strcmp(buf, "CCMP") == 0)
13648 security->encr = wifi_encryption_aes;
13649 else
13650 security->encr = wifi_encryption_aes_tkip;
13651 }
13652
developer9df4e652022-10-11 11:27:38 +080013653 if (security->mode != wifi_encryption_none) {
13654 memset(buf, 0, sizeof(buf));
13655 // wpa3 can use one or both configs as password, so we check sae_password first.
13656 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013657 if (strlen(buf) != 0) {
13658 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13659 security->u.key.type = wifi_security_key_type_sae;
13660 set_sae = TRUE;
13661 strncpy(security->u.key.key, buf, sizeof(buf));
13662 }
13663 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13664 if (strlen(buf) != 0){
13665 if (set_sae == TRUE)
13666 security->u.key.type = wifi_security_key_type_psk_sae;
13667 else if (strlen(buf) == 64)
13668 security->u.key.type = wifi_security_key_type_psk;
13669 else
13670 security->u.key.type = wifi_security_key_type_pass;
13671 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013672 }
developer9df4e652022-10-11 11:27:38 +080013673 security->u.key.key[255] = '\0';
13674 }
13675
developer587c1b62022-09-27 15:58:59 +080013676 memset(buf, 0, sizeof(buf));
13677 wifi_getApSecurityMFPConfig(ap_index, buf);
13678 if (strcmp(buf, "Disabled") == 0)
13679 security->mfp = wifi_mfp_cfg_disabled;
13680 else if (strcmp(buf, "Optional") == 0)
13681 security->mfp = wifi_mfp_cfg_optional;
13682 else if (strcmp(buf, "Required") == 0)
13683 security->mfp = wifi_mfp_cfg_required;
13684
13685 memset(buf, 0, sizeof(buf));
13686 security->wpa3_transition_disable = FALSE;
13687 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13688 disable = strtol(buf, NULL, 16);
13689 if (disable != 0)
13690 security->wpa3_transition_disable = TRUE;
13691
13692 memset(buf, 0, sizeof(buf));
13693 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13694 if (strlen(buf) == 0)
13695 security->rekey_interval = 86400;
13696 else
13697 security->rekey_interval = strtol(buf, NULL, 10);
13698
13699 memset(buf, 0, sizeof(buf));
13700 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13701 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013702 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013703 else
13704 security->strict_rekey = strtol(buf, NULL, 10);
13705
13706 memset(buf, 0, sizeof(buf));
13707 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13708 if (strlen(buf) == 0)
13709 security->eapol_key_retries = 4;
13710 else
13711 security->eapol_key_retries = strtol(buf, NULL, 10);
13712
13713 memset(buf, 0, sizeof(buf));
13714 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13715 if (strlen(buf) == 0)
13716 security->disable_pmksa_caching = FALSE;
13717 else
13718 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13719
13720 /* TODO
13721 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13722 */
13723 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13724 security->eap_identity_req_timeout = 0;
13725 security->eap_identity_req_retries = 0;
13726 security->eap_req_timeout = 0;
13727 security->eap_req_retries = 0;
13728 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013729 return RETURN_OK;
13730}
13731
13732#endif /* WIFI_HAL_VERSION_3 */
13733
13734#ifdef WIFI_HAL_VERSION_3_PHASE2
13735INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13736{
developerd946fd62022-12-08 18:03:28 +080013737 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013738 char cmd[128] = {0};
13739 char buf[128] = {0};
13740 char *mac_addr = NULL;
13741 BOOL status = FALSE;
13742 size_t len = 0;
13743
13744 if(ap_index > MAX_APS)
13745 return RETURN_ERR;
13746
13747 *output_numDevices = 0;
13748 wifi_getApEnable(ap_index, &status);
13749 if (status == FALSE)
13750 return RETURN_OK;
13751
developerac6f1142022-12-20 19:26:35 +080013752 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013753 return RETURN_ERR;
13754 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013755 _syscmd(cmd, buf, sizeof(buf));
13756
13757 mac_addr = strtok(buf, "\n");
13758 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13759 *output_numDevices = i + 1;
13760 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13761 addr_ptr = output_deviceMacAddressArray[i];
13762 mac_addr_aton(addr_ptr, mac_addr);
13763 mac_addr = strtok(NULL, "\n");
13764 }
13765
13766 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013767}
13768#else
13769INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13770{
developerd946fd62022-12-08 18:03:28 +080013771 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013772 char cmd[128];
13773 BOOL status = false;
13774
13775 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13776 return RETURN_ERR;
13777
13778 output_buf[0] = '\0';
13779
13780 wifi_getApEnable(ap_index,&status);
13781 if (!status)
13782 return RETURN_OK;
13783
developerac6f1142022-12-20 19:26:35 +080013784 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013785 return RETURN_ERR;
13786 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013787 _syscmd(cmd, output_buf, output_buf_size);
13788
13789 return RETURN_OK;
13790}
13791#endif
developer2f513ab2022-09-13 14:26:06 +080013792
13793INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13794{
13795 char output[16]={'\0'};
13796 char config_file[MAX_BUF_SIZE] = {0};
13797
13798 if (!enable)
13799 return RETURN_ERR;
13800
13801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13802 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13803
13804 if (strlen(output) == 0)
13805 *enable = FALSE;
13806 else if (strncmp(output, "1", 1) == 0)
13807 *enable = TRUE;
13808 else
13809 *enable = FALSE;
13810
13811 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13812 return RETURN_OK;
13813}
developer2d9c30f2022-09-13 15:06:14 +080013814
13815INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13816{
developer804c64f2022-10-19 13:54:40 +080013817 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013818 return RETURN_ERR;
13819 *output_enable=TRUE;
13820 return RETURN_OK;
13821}
developerfd7d2892022-09-13 16:44:53 +080013822
13823INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13824{
13825 char cmd[128] = {0};
13826 char buf[128] = {0};
13827 char line[128] = {0};
13828 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013829 FILE *f = NULL;
13830 int index = 0;
13831 int exp = 0;
13832 int mantissa = 0;
13833 int duration = 0;
13834 int radio_index = 0;
13835 int max_radio_num = 0;
13836 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013837 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013838 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13839
13840 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013841
developerfd7d2892022-09-13 16:44:53 +080013842 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013843
13844 phyId = radio_index_to_phy(radio_index);
13845 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013846 _syscmd(cmd, buf, sizeof(buf));
13847 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13848 if (*numSessionReturned > maxNumberSessions)
13849 *numSessionReturned = maxNumberSessions;
13850 else if (*numSessionReturned < 1) {
13851 *numSessionReturned = 0;
13852 return RETURN_OK;
13853 }
13854
developer033b37b2022-10-18 11:27:46 +080013855 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 +080013856 if ((f = popen(cmd, "r")) == NULL) {
13857 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13858 return RETURN_ERR;
13859 }
13860
13861 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013862 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013863 char *tmp = NULL;
13864 strcpy(buf, line);
13865 tmp = strtok(buf, " ");
13866 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13867 tmp = strtok(NULL, " ");
13868 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13869 tmp = strtok(NULL, " ");
13870 if (strstr(tmp, "t")) {
13871 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13872 }
13873 if (strstr(tmp, "a")) {
13874 twtSessions[index].twtParameters.operation.announced = TRUE;
13875 }
13876 tmp = strtok(NULL, " ");
13877 exp = strtol(tmp, NULL, 10);
13878 tmp = strtok(NULL, " ");
13879 mantissa = strtol(tmp, NULL, 10);
13880 tmp = strtok(NULL, " ");
13881 duration = strtol(tmp, NULL, 10);
13882
13883 // only implicit supported
13884 twtSessions[index].twtParameters.operation.implicit = TRUE;
13885 // only individual agreement supported
13886 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13887
13888 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13889 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013890 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013891 // Overflow handling
13892 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13893 } else {
13894 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13895 }
13896 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13897 index++;
13898 }
13899
13900 pclose(f);
13901 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13902 return RETURN_OK;
13903}