blob: e58b87e638a132eef80ab6feb159c596308257f6 [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
7846INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7847{
7848 unsigned int assoc_cnt = 0;
7849 char interface_name[50] = {0};
7850 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7851 char cmd[MAX_CMD_SIZE] = {'\0'};
7852 char line[256] = {'\0'};
7853 int i = 0;
7854 int ret = 0;
7855 const char *ptr = NULL;
7856 char *key = NULL;
7857 char *val = NULL;
7858 wifi_associated_dev3_t *temp = NULL;
7859 int rssi;
7860
7861 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7862
7863 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7864 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7865 return RETURN_ERR;
7866 }
7867
7868 // Example filtered output of 'iw dev' command:
7869 // Station 0a:69:72:10:d2:fa (on wifi0)
7870 // signal avg:-67 [-71, -71] dBm
7871 // Station 28:c2:1f:25:5f:99 (on wifi0)
7872 // signal avg:-67 [-71, -70] dBm
7873 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7874 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7875 return RETURN_ERR;
7876 }
7877
7878 ret = _syscmd(cmd, buf, sizeof(buf));
7879 if (ret == RETURN_ERR) {
7880 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7881 return RETURN_ERR;
7882 }
7883
7884 *output_array_size = count_occurences(buf, "Station");
7885 if (*output_array_size == 0) return RETURN_OK;
7886
7887 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7888 if (temp == NULL) {
7889 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7890 return RETURN_ERR;
7891 }
7892 *associated_dev_array = temp;
7893
7894 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7895 ptr = get_line_from_str_buf(buf, line);
7896 i = -1;
7897 while (ptr) {
7898 if (strstr(line, "Station")) {
7899 i++;
7900 key = strtok(line, " ");
7901 val = strtok(NULL, " ");
7902 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7903 &temp[i].cli_MACAddress[0],
7904 &temp[i].cli_MACAddress[1],
7905 &temp[i].cli_MACAddress[2],
7906 &temp[i].cli_MACAddress[3],
7907 &temp[i].cli_MACAddress[4],
7908 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7909 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7910 free(*associated_dev_array);
7911 return RETURN_ERR;
7912 }
7913 }
7914 else if (i < 0) {
7915 ptr = get_line_from_str_buf(ptr, line);
7916 continue; // We didn't detect 'station' entry yet
7917 }
7918 else if (strstr(line, "signal avg")) {
7919 key = strtok(line, ":");
7920 val = strtok(NULL, " ");
7921 if (sscanf(val, "%d", &rssi) <= 0 ) {
7922 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7923 free(*associated_dev_array);
7924 return RETURN_ERR;
7925 }
7926 temp[i].cli_RSSI = rssi;
7927 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7928 }
7929 // Here other fields can be parsed if added to filter of 'iw dev' command
7930
7931 ptr = get_line_from_str_buf(ptr, line);
7932 };
7933
7934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7935
7936 return RETURN_OK;
7937}
7938
7939#if 0
7940//To-do
7941INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7942{
7943 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7944
7945 //Using different approach to get required WiFi Parameters from system available commands
7946#if 0
7947 FILE *f;
7948 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7949 char cmd[256], buf[2048];
7950 char *param , *value, *line=NULL;
7951 size_t len = 0;
7952 ssize_t nread;
7953 wifi_associated_dev3_t *dev=NULL;
7954 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007955 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007956 _syscmd(cmd,buf,sizeof(buf));
7957 *output_array_size = atoi(buf);
7958
7959 if (*output_array_size <= 0)
7960 return RETURN_OK;
7961
7962 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7963 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007964 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007965 _syscmd(cmd,buf,sizeof(buf));
7966 f = fopen("/tmp/connected_devices.txt", "r");
7967 if (f==NULL)
7968 {
7969 *output_array_size=0;
7970 return RETURN_ERR;
7971 }
7972 while ((nread = getline(&line, &len, f)) != -1)
7973 {
7974 param = strtok(line,"=");
7975 value = strtok(NULL,"=");
7976
7977 if( strcmp("flags",param) == 0 )
7978 {
7979 value[strlen(value)-1]='\0';
7980 if(strstr (value,"AUTHORIZED") != NULL )
7981 {
7982 dev[auth_temp].cli_AuthenticationState = 1;
7983 dev[auth_temp].cli_Active = 1;
7984 auth_temp++;
7985 read_flag=1;
7986 }
7987 }
7988 if(read_flag==1)
7989 {
7990 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7991 {
7992 value[strlen(value)-1]='\0';
7993 sscanf(value, "%x:%x:%x:%x:%x:%x",
7994 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7995 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7996 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7997 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7998 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7999 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8000
8001 }
8002 else if( strcmp("rx_packets",param) == 0 )
8003 {
8004 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8005 }
8006
8007 else if( strcmp("tx_packets",param) == 0 )
8008 {
8009 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8010 }
8011
8012 else if( strcmp("rx_bytes",param) == 0 )
8013 {
8014 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8015 }
8016
8017 else if( strcmp("tx_bytes",param) == 0 )
8018 {
8019 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8020 mac_temp++;
8021 read_flag=0;
8022 }
8023 }
8024 }
8025
8026 *output_array_size = auth_temp;
8027 auth_temp=0;
8028 mac_temp=0;
8029 free(line);
8030 fclose(f);
8031#endif
8032 char interface_name[MAX_BUF_SIZE] = {0};
8033 char wifi_status[MAX_BUF_SIZE] = {0};
8034 char hostapdconf[MAX_BUF_SIZE] = {0};
8035
8036 wifi_associated_dev3_t *dev_array = NULL;
8037 ULONG wifi_count = 0;
8038
8039 *associated_dev_array = NULL;
8040 *output_array_size = 0;
8041
8042 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8043 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8044 {
8045 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8046
developerac6f1142022-12-20 19:26:35 +08008047 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008048
8049 if(strlen(interface_name) > 1)
8050 {
8051 wifihal_interfacestatus(wifi_status,interface_name);
8052 if(strcmp(wifi_status,"RUNNING") == 0)
8053 {
8054 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8055
8056 *associated_dev_array = dev_array;
8057 *output_array_size = wifi_count;
8058 }
8059 else
8060 {
8061 *associated_dev_array = NULL;
8062 }
8063 }
8064 }
8065
8066 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8067 return RETURN_OK;
8068}
8069#endif
8070
8071/* getIPAddress function */
8072/**
8073* @description Returning IpAddress of the Matched String
8074*
8075* @param
8076* @str Having MacAddress
8077* @ipaddr Having ipaddr
8078* @return The status of the operation
8079* @retval RETURN_OK if successful
8080* @retval RETURN_ERR if any error is detected
8081*
8082*/
8083
8084INT getIPAddress(char *str,char *ipaddr)
8085{
8086 FILE *fp = NULL;
8087 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8088 int LeaseTime = 0,ret = 0;
8089 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8090 {
8091 return RETURN_ERR;
8092 }
8093
8094 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8095 {
8096 /*
8097 Sample:sss
8098 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8099 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8100 */
8101 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008102 &(LeaseTime),
8103 phyAddr,
8104 ipAddr,
8105 hostName
8106 );
developer06a01d92022-09-07 16:32:39 +08008107 if(ret != 4)
8108 continue;
8109 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008110 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008111 }
developerd946fd62022-12-08 18:03:28 +08008112 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008113 return RETURN_OK;
8114}
8115
8116/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8117/**
8118* @description Returning Inactive wireless connected clients informations
8119*
8120* @param
8121* @filename Holding private_wifi 2g/5g content files
8122* @associated_dev_array Having inactiv wireless clients informations
8123* @output_array_size Returning Inactive wireless counts
8124* @return The status of the operation
8125* @retval RETURN_OK if successful
8126* @retval RETURN_ERR if any error is detected
8127*
8128*/
8129
8130INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8131{
8132 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8133 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8134 FILE *fp = NULL;
8135 int arr[MACADDRESS_SIZE] = {0};
8136 unsigned char mac[MACADDRESS_SIZE] = {0};
8137 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8138 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8139 fp = popen(buf,"r");
8140 if(fp == NULL)
8141 return RETURN_ERR;
8142 else
8143 {
8144 fgets(path,sizeof(path),fp);
8145 maccount = atoi(path);
8146 }
8147 pclose(fp);
8148 *output_array_size = maccount;
8149 wifi_associated_dev3_t* temp = NULL;
8150 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8151 *associated_dev_array = temp;
8152 if(temp == NULL)
8153 {
8154 printf("Error Statement. Insufficient memory \n");
8155 return RETURN_ERR;
8156 }
8157 memset(buf,0,sizeof(buf));
8158 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8159 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008160 if (fp == NULL) {
8161 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8162 return RETURN_ERR;
8163 }
developer06a01d92022-09-07 16:32:39 +08008164 for(count = 0; count < maccount ; count++)
8165 {
8166 fgets(path,sizeof(path),fp);
8167 for(i = 0; path[i]!='\n';i++)
8168 str[i]=path[i];
8169 str[i]='\0';
8170 getIPAddress(str,ipaddr);
8171 memset(buf,0,sizeof(buf));
8172 if(strlen(ipaddr) > 0)
8173 {
8174 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8175 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8176 {
8177 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8178 {
8179 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8180 {
8181 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8182
8183 }
8184 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8185 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]);
8186 }
8187 temp[count].cli_AuthenticationState = 0; //TODO
8188 temp[count].cli_Active = 0; //TODO
8189 temp[count].cli_SignalStrength = 0;
8190 }
8191 else //Active wireless clients info
8192 {
8193 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8194 {
8195 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8196 {
8197 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8198
8199 }
8200 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8201 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]);
8202 }
8203 temp[count].cli_Active = 1;
8204 }
8205 }
8206 memset(ipaddr,0,sizeof(ipaddr));
8207 }
8208 pclose(fp);
8209 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8210 return RETURN_OK;
8211}
8212//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8213//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8214//To get Band Steering Capability
8215INT wifi_getBandSteeringCapability(BOOL *support)
8216{
8217 *support = FALSE;
8218 return RETURN_OK;
8219}
8220
8221
8222//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8223//To get Band Steering enable status
8224INT wifi_getBandSteeringEnable(BOOL *enable)
8225{
8226 *enable = FALSE;
8227 return RETURN_OK;
8228}
8229
8230//To turn on/off Band steering
8231INT wifi_setBandSteeringEnable(BOOL enable)
8232{
8233 return RETURN_OK;
8234}
8235
8236//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8237//To get Band Steering AP group
8238INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8239{
8240 if (NULL == output_ApGroup)
8241 return RETURN_ERR;
8242
8243 strcpy(output_ApGroup, "1,2");
8244 return RETURN_OK;
8245}
8246
8247//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8248//to set and read the band steering BandUtilizationThreshold parameters
8249INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8250{
8251 return RETURN_ERR;
8252}
8253
8254INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8255{
8256 return RETURN_ERR;
8257}
8258
8259//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8260//to set and read the band steering RSSIThreshold parameters
8261INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8262{
8263 return RETURN_ERR;
8264}
8265
8266INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8267{
8268 return RETURN_ERR;
8269}
8270
8271
8272//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8273//to set and read the band steering physical modulation rate threshold parameters
8274INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8275{
8276 //If chip is not support, return -1
8277 return RETURN_ERR;
8278}
8279
8280INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8281{
8282 //If chip is not support, return -1
8283 return RETURN_ERR;
8284}
8285
8286//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8287//to set and read the inactivity time (in seconds) for steering under overload condition
8288INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8289{
8290 return RETURN_ERR;
8291}
8292
8293INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8294{
8295 return RETURN_ERR;
8296}
8297
8298//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8299//to set and read the inactivity time (in seconds) for steering under Idle condition
8300INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8301{
8302 return RETURN_ERR;
8303}
8304
8305INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8306{
8307 return RETURN_ERR;
8308}
8309
8310//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8311//pClientMAC[64]
8312//pSourceSSIDIndex[64]
8313//pDestSSIDIndex[64]
8314//pSteeringReason[256]
8315INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8316{
8317 //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
8318 *pSteeringTime=time(NULL);
8319 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8320 return RETURN_OK;
8321}
8322
8323INT wifi_ifConfigDown(INT apIndex)
8324{
8325 INT status = RETURN_OK;
8326 char cmd[64];
8327
8328 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8329 printf("%s: %s\n", __func__, cmd);
8330 system(cmd);
8331
8332 return status;
8333}
8334
8335INT wifi_ifConfigUp(INT apIndex)
8336{
developerd946fd62022-12-08 18:03:28 +08008337 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008338 char cmd[128];
8339 char buf[1024];
8340
developerac6f1142022-12-20 19:26:35 +08008341 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008342 return RETURN_ERR;
8343 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008344 _syscmd(cmd, buf, sizeof(buf));
8345 return 0;
8346}
8347
8348//>> Deprecated. Replace with wifi_applyRadioSettings
8349INT wifi_pushBridgeInfo(INT apIndex)
8350{
developerd946fd62022-12-08 18:03:28 +08008351 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008352 char ip[32] = {0};
8353 char subnet[32] = {0};
8354 char bridge[32] = {0};
8355 int vlanId = 0;
8356 char cmd[128] = {0};
8357 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008358
8359 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8360 wifi_getApVlanID(apIndex,&vlanId);
8361
developerac6f1142022-12-20 19:26:35 +08008362 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008363 return RETURN_ERR;
8364 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008365 _syscmd(cmd,buf, sizeof(buf));
8366
8367 return 0;
8368}
8369
8370INT wifi_pushChannel(INT radioIndex, UINT channel)
8371{
developerd946fd62022-12-08 18:03:28 +08008372 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008373 char cmd[128];
8374 char buf[1024];
8375 int apIndex;
8376
8377 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008378 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008379 return RETURN_ERR;
8380 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008381 _syscmd(cmd,buf, sizeof(buf));
8382
8383 return 0;
8384}
8385
8386INT wifi_pushChannelMode(INT radioIndex)
8387{
8388 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8389 return RETURN_ERR;
8390}
8391
8392INT wifi_pushDefaultValues(INT radioIndex)
8393{
8394 //Apply Comcast specified default radio settings instantly
8395 //AMPDU=1
8396 //AMPDUFrames=32
8397 //AMPDULim=50000
8398 //txqueuelen=1000
8399
8400 return RETURN_ERR;
8401}
8402
8403INT wifi_pushTxChainMask(INT radioIndex)
8404{
8405 //Apply default TxChainMask instantly
8406 return RETURN_ERR;
8407}
8408
8409INT wifi_pushRxChainMask(INT radioIndex)
8410{
8411 //Apply default RxChainMask instantly
8412 return RETURN_ERR;
8413}
8414
8415INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8416{
8417 INT status;
8418
8419 status = wifi_setSSIDName(apIndex,ssid);
8420 wifi_setApEnable(apIndex,FALSE);
8421 wifi_setApEnable(apIndex,TRUE);
8422
8423 return status;
8424}
8425
8426INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8427{
8428 //Apply default Ssid Advertisement instantly
8429 return RETURN_ERR;
8430}
8431
8432INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8433{
8434 INT status = RETURN_ERR;
8435 *output = 0;
8436 return RETURN_ERR;
8437}
8438
8439INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8440{
8441 return RETURN_OK;
8442}
8443
8444INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8445{
8446 return RETURN_OK;
8447}
8448
8449//To-do
8450INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8451{
developereb199ae2022-09-13 14:04:27 +08008452 char output[16]={'\0'};
8453 char config_file[MAX_BUF_SIZE] = {0};
8454
8455 if (!output_string)
8456 return RETURN_ERR;
8457
8458 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8459 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8460
8461 if (strlen(output) == 0)
8462 snprintf(output_string, 64, "Disabled");
8463 else if (strncmp(output, "0", 1) == 0)
8464 snprintf(output_string, 64, "Disabled");
8465 else if (strncmp(output, "1", 1) == 0)
8466 snprintf(output_string, 64, "Optional");
8467 else if (strncmp(output, "2", 1) == 0)
8468 snprintf(output_string, 64, "Required");
8469 else {
8470 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8471 return RETURN_ERR;
8472 }
8473
8474 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008475 return RETURN_OK;
8476}
8477INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8478{
developereb199ae2022-09-13 14:04:27 +08008479 char str[MAX_BUF_SIZE]={'\0'};
8480 char cmd[MAX_CMD_SIZE]={'\0'};
8481 struct params params;
8482 char config_file[MAX_BUF_SIZE] = {0};
8483
8484 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8485 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8486 return RETURN_ERR;
8487
8488 params.name = "ieee80211w";
8489 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8490 params.value = "0";
8491 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8492 params.value = "1";
8493 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8494 params.value = "2";
8495 else{
8496 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8497 return RETURN_ERR;
8498 }
8499 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8500 wifi_hostapdWrite(config_file, &params, 1);
8501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008502 return RETURN_OK;
8503}
8504INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8505{
8506 char output[16]={'\0'};
8507 char config_file[MAX_BUF_SIZE] = {0};
8508
8509 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8510 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8511 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8512
8513 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8514 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8515
8516 return RETURN_OK;
8517}
8518
8519INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8520{
8521 return RETURN_OK;
8522}
8523
8524INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8525{
8526 return RETURN_OK;
8527}
8528
8529INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8530{
8531 return RETURN_OK;
8532}
8533
8534INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8535{
8536 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8537 char config_file[MAX_BUF_SIZE] = {0};
8538
8539 if (NULL == output)
8540 return RETURN_ERR;
8541 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8542 wifi_hostapdRead(config_file,"hw_mode",output,64);
8543
8544 if(strcmp(output,"b")==0)
8545 sprintf(output, "%s", "1,2,5.5,11");
8546 else if (strcmp(output,"a")==0)
8547 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8548 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8549 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8550
8551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8552 return RETURN_OK;
8553}
8554
8555INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8556{
8557 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8558 char *temp;
8559 char temp_output[128];
8560 char temp_TransmitRates[128];
8561 char config_file[MAX_BUF_SIZE] = {0};
8562
8563 if (NULL == output)
8564 return RETURN_ERR;
8565
8566 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8567 wifi_hostapdRead(config_file,"supported_rates",output,64);
8568
developer5b398df2022-11-17 20:39:48 +08008569 if (strlen(output) == 0) {
8570 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8571 return RETURN_OK;
8572 }
developer06a01d92022-09-07 16:32:39 +08008573 strcpy(temp_TransmitRates,output);
8574 strcpy(temp_output,"");
8575 temp = strtok(temp_TransmitRates," ");
8576 while(temp!=NULL)
8577 {
8578 temp[strlen(temp)-1]=0;
8579 if((temp[0]=='5') && (temp[1]=='\0'))
8580 {
8581 temp="5.5";
8582 }
8583 strcat(temp_output,temp);
8584 temp = strtok(NULL," ");
8585 if(temp!=NULL)
8586 {
8587 strcat(temp_output,",");
8588 }
8589 }
8590 strcpy(output,temp_output);
8591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8592
8593 return RETURN_OK;
8594}
8595
8596INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8597{
8598 return RETURN_OK;
8599}
8600
8601
8602INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8603{
8604 int i=0;
8605 char *temp;
developeref938762022-10-19 17:21:01 +08008606 char temp1[128] = {0};
8607 char temp_output[128] = {0};
8608 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008609 struct params params={'\0'};
8610 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008611 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008612
8613 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8614 if(NULL == output)
8615 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008616 strcpy(temp_TransmitRates,output);
8617
8618 for(i=0;i<strlen(temp_TransmitRates);i++)
8619 {
developeref938762022-10-19 17:21:01 +08008620 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008621 {
8622 continue;
8623 }
8624 else
8625 {
8626 return RETURN_ERR;
8627 }
8628 }
8629 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008630 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008631 while(temp!=NULL)
8632 {
8633 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008634 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008635 {
developeref938762022-10-19 17:21:01 +08008636 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008637 {
8638 return RETURN_ERR;
8639 }
8640 }
8641
8642 if(strcmp(temp,"5.5")==0)
8643 {
8644 strcpy(temp1,"55");
8645 }
8646 else
8647 {
8648 strcat(temp1,"0");
8649 }
8650 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008651 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008652 if(temp!=NULL)
8653 {
8654 strcat(temp_output," ");
8655 }
8656 }
8657 strcpy(output,temp_output);
8658
developer06a01d92022-09-07 16:32:39 +08008659 params.name = "supported_rates";
8660 params.value = output;
8661
8662 wifi_dbg_printf("\n%s:",__func__);
8663 wifi_dbg_printf("params.value=%s\n",params.value);
8664 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8665 wifi_hostapdWrite(config_file,&params,1);
8666 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8667
8668 return RETURN_OK;
8669}
8670
8671
8672static char *sncopy(char *dst, int dst_sz, const char *src)
8673{
8674 if (src && dst && dst_sz > 0) {
8675 strncpy(dst, src, dst_sz);
8676 dst[dst_sz - 1] = '\0';
8677 }
8678 return dst;
8679}
8680
8681static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8682{
8683 if (0 == strcmp(ht_mode, "HT40") ||
8684 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008685 0 == strcmp(ht_mode, "HT160") ||
8686 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008687 switch (channel) {
developer9a520b12023-09-21 16:01:43 +08008688 case 0 ... 7:
developer06a01d92022-09-07 16:32:39 +08008689 case 36:
8690 case 44:
8691 case 52:
8692 case 60:
8693 case 100:
8694 case 108:
8695 case 116:
8696 case 124:
8697 case 132:
8698 case 140:
8699 case 149:
8700 case 157:
8701 return 1;
8702 case 8 ... 13:
8703 case 40:
8704 case 48:
8705 case 56:
8706 case 64:
8707 case 104:
8708 case 112:
8709 case 120:
8710 case 128:
8711 case 136:
8712 case 144:
8713 case 153:
8714 case 161:
8715 return -1;
8716 default:
8717 return -EINVAL;
8718 }
8719 }
8720
8721 return -EINVAL;
8722}
8723
developerb7593de2022-10-18 09:51:57 +08008724static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8725{
8726 int idx = channel%8;
8727 if (0 == strcmp(ht_mode, "HT40") ||
8728 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008729 0 == strcmp(ht_mode, "HT160") ||
8730 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008731 switch (idx) {
8732 case 1:
8733 return 1;
8734 case 5:
8735 return -1;
8736 default:
8737 return -EINVAL;
8738 }
8739 }
8740
8741 return -EINVAL;
8742}
developer06a01d92022-09-07 16:32:39 +08008743static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8744{
8745 if (NULL == hw_mode) return;
8746
8747 if (0 == strcmp(hw_mode, "ac"))
8748 sncopy(bw_mode, bw_mode_len, "ht vht");
8749
8750 if (0 == strcmp(hw_mode, "n"))
8751 sncopy(bw_mode, bw_mode_len, "ht");
8752
8753 return;
8754}
8755
8756static int util_chan_to_freq(int chan)
8757{
8758 if (chan == 14)
8759 return 2484;
8760 else if (chan < 14)
8761 return 2407 + chan * 5;
8762 else if (chan >= 182 && chan <= 196)
8763 return 4000 + chan * 5;
8764 else
8765 return 5000 + chan * 5;
8766 return 0;
8767}
8768
developerb7593de2022-10-18 09:51:57 +08008769static int util_6G_chan_to_freq(int chan)
8770{
8771 if (chan)
8772 return 5950 + chan * 5;
8773 else
8774 return 0;
8775
8776}
developer06a01d92022-09-07 16:32:39 +08008777const int *util_unii_5g_chan2list(int chan, int width)
8778{
8779 static const int lists[] = {
8780 // <width>, <chan1>, <chan2>..., 0,
8781 20, 36, 0,
8782 20, 40, 0,
8783 20, 44, 0,
8784 20, 48, 0,
8785 20, 52, 0,
8786 20, 56, 0,
8787 20, 60, 0,
8788 20, 64, 0,
8789 20, 100, 0,
8790 20, 104, 0,
8791 20, 108, 0,
8792 20, 112, 0,
8793 20, 116, 0,
8794 20, 120, 0,
8795 20, 124, 0,
8796 20, 128, 0,
8797 20, 132, 0,
8798 20, 136, 0,
8799 20, 140, 0,
8800 20, 144, 0,
8801 20, 149, 0,
8802 20, 153, 0,
8803 20, 157, 0,
8804 20, 161, 0,
8805 20, 165, 0,
8806 40, 36, 40, 0,
8807 40, 44, 48, 0,
8808 40, 52, 56, 0,
8809 40, 60, 64, 0,
8810 40, 100, 104, 0,
8811 40, 108, 112, 0,
8812 40, 116, 120, 0,
8813 40, 124, 128, 0,
8814 40, 132, 136, 0,
8815 40, 140, 144, 0,
8816 40, 149, 153, 0,
8817 40, 157, 161, 0,
8818 80, 36, 40, 44, 48, 0,
8819 80, 52, 56, 60, 64, 0,
8820 80, 100, 104, 108, 112, 0,
8821 80, 116, 120, 124, 128, 0,
8822 80, 132, 136, 140, 144, 0,
8823 80, 149, 153, 157, 161, 0,
8824 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8825 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8826 -1 // final delimiter
8827 };
8828 const int *start;
8829 const int *p;
8830
8831 for (p = lists; *p != -1; p++) {
8832 if (*p == width) {
8833 for (start = ++p; *p != 0; p++) {
8834 if (*p == chan)
8835 return start;
8836 }
8837 }
8838 // move to the end of channel list of given width
8839 while (*p != 0) {
8840 p++;
8841 }
8842 }
8843
8844 return NULL;
8845}
8846
8847static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8848{
8849 if (NULL == ht_mode)
8850 return 0;
8851
8852 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8853 const int *chans = util_unii_5g_chan2list(channel, width);
8854 int sum = 0;
8855 int cnt = 0;
8856
8857 if (NULL == chans)
8858 return 0;
8859
8860 while (*chans) {
8861 sum += *chans;
8862 cnt++;
8863 chans++;
8864 }
developer30423732022-12-01 16:17:49 +08008865 if (cnt == 0)
8866 return 0;
developer06a01d92022-09-07 16:32:39 +08008867 return sum / cnt;
8868}
8869
developerb7593de2022-10-18 09:51:57 +08008870static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8871{
8872 if (NULL == ht_mode)
8873 return 0;
8874
8875 int width = strtol((ht_mode + 2), NULL, 10);
8876
8877 int idx = 0 ;
8878 int centerchan = 0;
8879 int chan_ofs = 1;
8880
8881 if (width == 40){
8882 idx = ((channel/4) + chan_ofs)%2;
8883 switch (idx) {
8884 case 0:
8885 centerchan = (channel - 2);
8886 break;
8887 case 1:
8888 centerchan = (channel + 2);
8889 break;
8890 default:
8891 return -EINVAL;
8892 }
8893 }else if (width == 80){
8894 idx = ((channel/4) + chan_ofs)%4;
8895 switch (idx) {
8896 case 0:
8897 centerchan = (channel - 6);
8898 break;
8899 case 1:
8900 centerchan = (channel + 6);
8901 break;
8902 case 2:
8903 centerchan = (channel + 2);
8904 break;
8905 case 3:
8906 centerchan = (channel - 2);
8907 break;
8908 default:
8909 return -EINVAL;
8910 }
8911 }else if (width == 160){
8912 switch (channel) {
8913 case 1 ... 29:
8914 centerchan = 15;
8915 break;
8916 case 33 ... 61:
8917 centerchan = 47;
8918 break;
8919 case 65 ... 93:
8920 centerchan = 79;
8921 break;
8922 case 97 ... 125:
8923 centerchan = 111;
8924 break;
8925 case 129 ... 157:
8926 centerchan = 143;
8927 break;
8928 case 161 ... 189:
8929 centerchan = 175;
8930 break;
8931 case 193 ... 221:
8932 centerchan = 207;
8933 break;
8934 default:
8935 return -EINVAL;
8936 }
developer7c4cd202023-03-01 10:56:29 +08008937 }else if (width == 320){
8938 switch (channel) {
8939 case 1 ... 29:
8940 centerchan = 31;
8941 break;
8942 case 33 ... 93:
8943 centerchan = 63;
8944 break;
8945 case 97 ... 157:
8946 centerchan = 127;
8947 break;
8948 case 161 ... 221:
8949 centerchan = 191;
8950 break;
8951 default:
8952 return -EINVAL;
8953 }
developerb7593de2022-10-18 09:51:57 +08008954 }
8955 return centerchan;
8956}
developer06a01d92022-09-07 16:32:39 +08008957static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8958{
8959 BOOL onlyG, onlyN, onlyA;
8960 CHAR tmp[64];
8961 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8962 if (ret == RETURN_OK) {
8963 sncopy(hw_mode, hw_mode_size, tmp);
8964 }
8965 return ret;
8966}
8967
8968INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8969{
8970 // Sample commands:
8971 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8972 // hostapd_cli -i wifi0 chan_switch 30 2437
8973 char cmd[MAX_CMD_SIZE] = {0};
8974 char buf[MAX_BUF_SIZE] = {0};
8975 int freq = 0, ret = 0;
8976 char center_freq1_str[32] = ""; // center_freq1=%d
8977 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8978 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8979 char hw_mode[16] = ""; // n|ac
8980 char bw_mode[16] = ""; // ht|ht vht
8981 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008982 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008983 int sec_chan_offset;
8984 int width;
developer4fb0b922022-09-30 14:29:09 +08008985 char config_file[64] = {0};
8986 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08008987 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08008988 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008989 wifi_band band = band_invalid;
8990 int center_chan = 0;
8991 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008992
developer4fb0b922022-09-30 14:29:09 +08008993 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008994
developerac6f1142022-12-20 19:26:35 +08008995 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008996 return RETURN_ERR;
8997
developer06a01d92022-09-07 16:32:39 +08008998 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8999
developerb7593de2022-10-18 09:51:57 +08009000 band = wifi_index_to_band(radioIndex);
9001
developer5884e982022-10-06 10:52:50 +08009002 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08009003
9004 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08009005 if (channel){
developerb7593de2022-10-18 09:51:57 +08009006 if (band == band_6){
9007 freq = util_6G_chan_to_freq(channel);
9008 }else{
9009 freq = util_chan_to_freq(channel);
9010 }
developer7c4cd202023-03-01 10:56:29 +08009011 if (width == 320) {
9012 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
9013 setEHT320 = TRUE;
9014 }
developer5884e982022-10-06 10:52:50 +08009015 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08009016
developer5884e982022-10-06 10:52:50 +08009017 // Provide bandwith if specified
9018 if (channel_width_MHz > 20) {
9019 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9020 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9021 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08009022
developer5884e982022-10-06 10:52:50 +08009023 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9024 }else if (channel_width_MHz == 20){
9025 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9026 }
developer06a01d92022-09-07 16:32:39 +08009027
developerb7593de2022-10-18 09:51:57 +08009028
developer5884e982022-10-06 10:52:50 +08009029 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08009030 if (band == band_6){
9031 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9032 if(center_chan){
9033 center_freq1 = util_6G_chan_to_freq(center_chan);
9034 }
9035 }else{
9036 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9037 if(center_chan){
9038 center_freq1 = util_chan_to_freq(center_chan);
9039 }
developer5884e982022-10-06 10:52:50 +08009040 }
developerb7593de2022-10-18 09:51:57 +08009041
9042 if (center_freq1)
9043 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9044
9045 }
9046
9047 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9048 if (band == band_6){
9049 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9050 }else{
9051 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009052 }
developerb7593de2022-10-18 09:51:57 +08009053 if (sec_chan_offset != -EINVAL)
9054 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009055
developer5884e982022-10-06 10:52:50 +08009056 // Only the first AP, other are hanging on the same radio
9057 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009058 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9059 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009060 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9061 wifi_dbg_printf("execute: '%s'\n", cmd);
9062 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009063 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009064
developer5884e982022-10-06 10:52:50 +08009065 ret = wifi_setRadioChannel(radioIndex, channel);
9066 if (ret != RETURN_OK) {
9067 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9068 return RETURN_ERR;
9069 }
9070
9071 if (sec_chan_offset == 1) ext_str = "Above";
9072 else if (sec_chan_offset == -1) ext_str = "Below";
9073
9074 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009075
developer5884e982022-10-06 10:52:50 +08009076 } else {
9077 if (channel_width_MHz > 20)
9078 ext_str = "Above";
9079 }
developer4fb0b922022-09-30 14:29:09 +08009080
developer06a01d92022-09-07 16:32:39 +08009081 char mhz_str[16];
9082 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009083 if (setEHT320 == TRUE)
9084 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9085 else
9086 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009087
developer57fa24a2023-03-15 17:25:07 +08009088 writeBandWidth(radioIndex, mhz_str);
9089 if (band == band_2_4 || band == band_5) {
9090 if (width == 20)
9091 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9092 else
9093 wifi_setRadioExtChannel(radioIndex, ext_str);
9094 }
developer06a01d92022-09-07 16:32:39 +08009095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9096
9097 return RETURN_OK;
9098}
9099
9100INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9101{
developer615510b2022-09-27 10:14:35 +08009102 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009103 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009104 char cmd[256]={0};
9105 char buf[128]={0};
9106 char file_name[32] = {0};
9107 char filter_SSID[32] = {0};
9108 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009109 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009110 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009111 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009112 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009113 size_t len=0;
9114 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009115 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009116 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009117 bool filter_enable = false;
9118 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009119 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009120
developer615510b2022-09-27 10:14:35 +08009121 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009122
developer615510b2022-09-27 10:14:35 +08009123 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9124 f = fopen(file_name, "r");
9125 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009126 fgets(buf, sizeof(file_name), f);
9127 if ((strncmp(buf, "0", 1)) != 0) {
9128 fgets(filter_SSID, sizeof(file_name), f);
9129 if (strlen(filter_SSID) != 0)
9130 filter_enable = true;
9131 }
developer615510b2022-09-27 10:14:35 +08009132 fclose(f);
9133 }
9134
developerac6f1142022-12-20 19:26:35 +08009135 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009136 return RETURN_ERR;
9137
developer033b37b2022-10-18 11:27:46 +08009138 phyId = radio_index_to_phy(radio_index);
9139
9140 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009141 _syscmd(cmd, buf, sizeof(buf));
9142 channels_num = strtol(buf, NULL, 10);
9143
developerd946fd62022-12-08 18:03:28 +08009144 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9145 // 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 +08009146 fprintf(stderr, "cmd: %s\n", cmd);
9147 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009148 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9149 return RETURN_ERR;
9150 }
developer5550e242022-09-30 09:59:32 +08009151
9152 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9153 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9154
developer615510b2022-09-27 10:14:35 +08009155 ret = fgets(line, sizeof(line), f);
9156 while (ret != NULL) {
9157 if(strstr(line, "BSS") != NULL) { // new neighbor info
9158 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9159 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9160 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9161
9162 if (!filter_BSS) {
9163 index++;
9164 wifi_neighbor_ap2_t *tmp;
9165 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9166 if (tmp == NULL) { // no more memory to use
9167 index--;
9168 wifi_dbg_printf("%s: realloc failed\n", __func__);
9169 break;
9170 }
9171 scan_array = tmp;
9172 }
9173 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009174
developer615510b2022-09-27 10:14:35 +08009175 filter_BSS = false;
9176 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9177 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9178 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9179 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9180 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009181 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009182 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009183
developer615510b2022-09-27 10:14:35 +08009184 if (freq >= 2412 && freq <= 2484) {
9185 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9186 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9187 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9188 }
9189 else if (freq >= 5160 && freq <= 5805) {
9190 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9191 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9192 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9193 }
developer06a01d92022-09-07 16:32:39 +08009194
developer615510b2022-09-27 10:14:35 +08009195 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009196 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009197 for (int i = 0; i < channels_num; i++) {
9198 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9199 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9200 break;
9201 }
9202 }
developer06a01d92022-09-07 16:32:39 +08009203 }
developer615510b2022-09-27 10:14:35 +08009204 } else if (strstr(line, "beacon interval") != NULL) {
9205 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9206 } else if (strstr(line, "signal") != NULL) {
9207 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9208 } else if (strstr(line,"SSID") != NULL) {
9209 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9210 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9211 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009212 }
developer615510b2022-09-27 10:14:35 +08009213 } else if (strstr(line, "Supported rates") != NULL) {
9214 char SRate[80] = {0}, *tmp = NULL;
9215 memset(buf, 0, sizeof(buf));
9216 strcpy(SRate, line);
9217 tmp = strtok(SRate, ":");
9218 tmp = strtok(NULL, ":");
9219 strcpy(buf, tmp);
9220 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009221
developer615510b2022-09-27 10:14:35 +08009222 tmp = strtok(buf, " \n");
9223 while (tmp != NULL) {
9224 strcat(SRate, tmp);
9225 if (SRate[strlen(SRate) - 1] == '*') {
9226 SRate[strlen(SRate) - 1] = '\0';
9227 }
9228 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009229
developer615510b2022-09-27 10:14:35 +08009230 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009231 }
developer615510b2022-09-27 10:14:35 +08009232 SRate[strlen(SRate) - 1] = '\0';
9233 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9234 } else if (strstr(line, "DTIM") != NULL) {
9235 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9236 } else if (strstr(line, "VHT capabilities") != NULL) {
9237 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9238 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9239 } else if (strstr(line, "HT capabilities") != NULL) {
9240 strcat(scan_array[index].ap_SupportedStandards, ",n");
9241 strcpy(scan_array[index].ap_OperatingStandards, "n");
9242 } else if (strstr(line, "VHT operation") != NULL) {
9243 ret = fgets(line, sizeof(line), f);
9244 sscanf(line," * channel width: %d", &vht_channel_width);
9245 if(vht_channel_width == 1) {
9246 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9247 } else {
9248 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9249 }
9250 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9251 continue;
9252 } else if (strstr(line, "HT operation") != NULL) {
9253 ret = fgets(line, sizeof(line), f);
9254 sscanf(line," * secondary channel offset: %s", &buf);
9255 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009256 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009257 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 +08009258 }
developer615510b2022-09-27 10:14:35 +08009259 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009260 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009261 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9262 } else {
9263 //20Mhz
9264 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 +08009265 }
developer615510b2022-09-27 10:14:35 +08009266 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009267 continue;
developer615510b2022-09-27 10:14:35 +08009268 } else if (strstr(line, "HE capabilities") != NULL) {
9269 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9270 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9271 ret = fgets(line, sizeof(line), f);
9272 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9273 if (strstr(line, "HE40/2.4GHz") != NULL)
9274 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9275 else
9276 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9277 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9278 if (strstr(line, "HE80/5GHz") != NULL) {
9279 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9280 ret = fgets(line, sizeof(line), f);
9281 } else
9282 continue;
9283 if (strstr(line, "HE160/5GHz") != NULL)
9284 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009285 }
developer615510b2022-09-27 10:14:35 +08009286 continue;
9287 } else if (strstr(line, "WPA") != NULL) {
9288 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9289 } else if (strstr(line, "RSN") != NULL) {
9290 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9291 } else if (strstr(line, "Group cipher") != NULL) {
9292 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9293 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9294 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009295 }
developer06a01d92022-09-07 16:32:39 +08009296 }
developer615510b2022-09-27 10:14:35 +08009297 ret = fgets(line, sizeof(line), f);
9298 }
9299
9300 if (!filter_BSS) {
9301 *output_array_size = index + 1;
9302 } else {
9303 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9304 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009305 }
developer06a01d92022-09-07 16:32:39 +08009306 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009307 pclose(f);
developer5550e242022-09-30 09:59:32 +08009308 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009309 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009310 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009311}
developer615510b2022-09-27 10:14:35 +08009312
developer06a01d92022-09-07 16:32:39 +08009313INT wifi_getApAssociatedDeviceStats(
9314 INT apIndex,
9315 mac_address_t *clientMacAddress,
9316 wifi_associated_dev_stats_t *associated_dev_stats,
9317 u64 *handle)
9318{
9319 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9320 char interface_name[50] = {0};
9321 char cmd[1024] = {0};
9322 char mac_str[18] = {0};
9323 char *key = NULL;
9324 char *val = NULL;
9325 FILE *f = NULL;
9326 char *line = NULL;
9327 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009328
9329 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9330 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9331 return RETURN_ERR;
9332 }
9333
9334 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9335 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9336 if((f = popen(cmd, "r")) == NULL) {
9337 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9338 return RETURN_ERR;
9339 }
9340
developer30423732022-12-01 16:17:49 +08009341 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009342 key = strtok(line,":");
9343 val = strtok(NULL,":");
9344
9345 if(!strncmp(key,"rx bytes",8))
9346 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9347 if(!strncmp(key,"tx bytes",8))
9348 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9349 if(!strncmp(key,"rx packets",10))
9350 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9351 if(!strncmp(key,"tx packets",10))
9352 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9353 if(!strncmp(key,"tx retries",10))
9354 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9355 if(!strncmp(key,"tx failed",9))
9356 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9357 if(!strncmp(key,"rx drop misc",13))
9358 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9359 if(!strncmp(key,"rx bitrate",10)) {
9360 val = strtok(val, " ");
9361 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9362 }
9363 if(!strncmp(key,"tx bitrate",10)) {
9364 val = strtok(val, " ");
9365 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9366 }
9367 }
9368 free(line);
9369 pclose(f);
9370 return RETURN_OK;
9371}
9372
9373INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9374{
developerd946fd62022-12-08 18:03:28 +08009375 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009376 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9377
9378 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9379 if (NULL == output_string)
9380 return RETURN_ERR;
9381
developerac6f1142022-12-20 19:26:35 +08009382 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009383 return RETURN_ERR;
9384 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 +08009385 _syscmd(cmd, buf, sizeof(buf));
9386
9387 //size of SSID name restricted to value less than 32 bytes
9388 snprintf(output_string, 32, "%s", buf);
9389 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9390
9391 return RETURN_OK;
9392}
9393
9394INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9395{
9396 //char cmd[MAX_CMD_SIZE] = {0};
9397 char config_file[MAX_BUF_SIZE] = {0};
9398 char buf[32] = {0};
9399
9400 if (!output_filterMode)
9401 return RETURN_ERR;
9402
9403 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9404 //_syscmd(cmd, buf, sizeof(buf));
9405 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9406 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009407 if(strlen(buf) == 0) {
9408 *output_filterMode = 0;
9409 }
9410 else {
9411 int macaddr_acl_mode = strtol(buf, NULL, 10);
9412 if (macaddr_acl_mode == 1) {
9413 *output_filterMode = 1;
9414 } else if (macaddr_acl_mode == 0) {
9415 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9416 if (strlen(buf) == 0) {
9417 *output_filterMode = 0;
9418 } else {
9419 *output_filterMode = 2;
9420 }
9421 } else {
9422 return RETURN_ERR;
9423 }
9424 }
developer06a01d92022-09-07 16:32:39 +08009425
9426 return RETURN_OK;
9427}
9428
9429INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9430{
9431 FILE *fp = NULL;
9432 char str[MAX_BUF_SIZE] = {0};
9433 int wificlientindex = 0 ;
9434 int count = 0;
9435 int signalstrength = 0;
9436 int arr[MACADDRESS_SIZE] = {0};
9437 unsigned char mac[MACADDRESS_SIZE] = {0};
9438 UINT wifi_count = 0;
9439 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9440 char pipeCmd[MAX_CMD_SIZE] = {0};
9441
9442 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9443 *output_array_size = 0;
9444 *associated_dev_array = NULL;
9445 char interface_name[50] = {0};
9446
9447 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9448 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9449 return RETURN_ERR;
9450 }
9451
9452 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9453 fp = popen(pipeCmd, "r");
9454 if (fp == NULL)
9455 {
9456 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9457 return RETURN_ERR;
9458 }
9459
9460 /* Read the output a line at a time - output it. */
9461 fgets(str, sizeof(str)-1, fp);
9462 wifi_count = (unsigned int) atoi ( str );
9463 *output_array_size = wifi_count;
9464 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9465 pclose(fp);
9466
9467 if(wifi_count == 0)
9468 {
9469 return RETURN_OK;
9470 }
9471 else
9472 {
9473 wifi_associated_dev2_t* temp = NULL;
9474 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9475 *associated_dev_array = temp;
9476 if(temp == NULL)
9477 {
9478 printf("Error Statement. Insufficient memory \n");
9479 return RETURN_ERR;
9480 }
9481
9482 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9483 system(pipeCmd);
9484
9485 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9486 if(fp == NULL)
9487 {
9488 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9489 return RETURN_ERR;
9490 }
9491 fclose(fp);
9492
developer30423732022-12-01 16:17:49 +08009493 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009494 fp = popen(pipeCmd, "r");
9495 if(fp)
9496 {
9497 for(count =0 ; count < wifi_count; count++)
9498 {
9499 fgets(str, MAX_BUF_SIZE, fp);
9500 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9501 {
9502 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9503 {
9504 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9505
9506 }
9507 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9508 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]);
9509 }
9510 temp[count].cli_AuthenticationState = 1; //TODO
9511 temp[count].cli_Active = 1; //TODO
9512 }
9513 pclose(fp);
9514 }
9515
9516 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009517 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 +08009518 fp = popen(pipeCmd, "r");
9519 if(fp)
9520 {
9521 pclose(fp);
9522 }
9523 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9524 if(fp)
9525 {
9526 for(count =0 ; count < wifi_count ;count++)
9527 {
9528 fgets(str, MAX_BUF_SIZE, fp);
9529 signalstrength = atoi(str);
9530 temp[count].cli_RSSI = signalstrength;
9531 }
9532 pclose(fp);
9533 }
9534
9535
9536 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009537 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 +08009538 fp = popen(pipeCmd, "r");
9539 if (fp)
9540 {
9541 pclose(fp);
9542 }
9543 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9544 if (fp)
9545 {
9546 for (count = 0; count < wifi_count; count++)
9547 {
9548 fgets(str, MAX_BUF_SIZE, fp);
9549 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9550 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9551 }
9552 pclose(fp);
9553 }
9554
9555 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009556 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 +08009557 fp = popen(pipeCmd, "r");
9558 if (fp)
9559 {
9560 pclose(fp);
9561 }
9562 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9563 if (fp)
9564 {
9565 for (count = 0; count < wifi_count; count++)
9566 {
9567 fgets(str, MAX_BUF_SIZE, fp);
9568 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9569 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9570 }
9571 pclose(fp);
9572 }
9573 }
9574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9575 return RETURN_OK;
9576
9577}
9578
9579INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9580{
9581#if 0
9582 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009583 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009584 _syscmd(cmd, buf, sizeof(buf));*/
9585
9586 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9587 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9588 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9589 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9590
9591 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.
9592 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].
9593 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].
9594 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].
9595 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9596 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9597
9598 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9599 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9600 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9601 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.
9602 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.
9603 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.
9604 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.
9605 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.
9606 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.
9607 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.
9608 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9609#endif
9610
9611 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009612 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009613 char pipeCmd[128] = {0};
9614 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009615 wifi_ssidTrafficStats2_t *out = output_struct;
9616
developerce736392022-09-13 15:24:34 +08009617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009618 if (!output_struct)
9619 return RETURN_ERR;
9620
developerce736392022-09-13 15:24:34 +08009621 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009622 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009623 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009624 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009625
developer06a01d92022-09-07 16:32:39 +08009626 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009627 if (fp == NULL) {
9628 fprintf(stderr, "%s: popen failed\n", __func__);
9629 return RETURN_ERR;
9630 }
9631 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009632 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009633
developerce736392022-09-13 15:24:34 +08009634 if (strlen(str) == 0) // interface not exist
9635 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009636
developerce736392022-09-13 15:24:34 +08009637 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9638 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009639
developerce736392022-09-13 15:24:34 +08009640 memset(str, 0, sizeof(str));
9641 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009642 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009643 if (fp == NULL) {
9644 fprintf(stderr, "%s: popen failed\n", __func__);
9645 return RETURN_ERR;
9646 }
9647 fgets(str, sizeof(str), fp);
9648
9649 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9650 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009651 pclose(fp);
developerce736392022-09-13 15:24:34 +08009652
9653 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9654 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9655
9656 // Not supported
9657 output_struct->ssid_RetransCount = 0;
9658 output_struct->ssid_FailedRetransCount = 0;
9659 output_struct->ssid_RetryCount = 0;
9660 output_struct->ssid_MultipleRetryCount = 0;
9661 output_struct->ssid_ACKFailureCount = 0;
9662 output_struct->ssid_AggregatedPacketCount = 0;
9663
developer06a01d92022-09-07 16:32:39 +08009664 return RETURN_OK;
9665}
9666
9667//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).
9668INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9669{
9670 char output_val[16]={'\0'};
9671 char config_file[MAX_BUF_SIZE] = {0};
9672
9673 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9674 if (!output)
9675 return RETURN_ERR;
9676 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9677 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9678
9679 if( strcmp(output_val,"1") == 0 )
9680 *output = TRUE;
9681 else
9682 *output = FALSE;
9683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9684
9685 return RETURN_OK;
9686}
9687
9688INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9689{
9690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9691 char str[MAX_BUF_SIZE]={'\0'};
9692 char string[MAX_BUF_SIZE]={'\0'};
9693 char cmd[MAX_CMD_SIZE]={'\0'};
9694 char *ch;
9695 char config_file[MAX_BUF_SIZE] = {0};
9696 struct params params;
9697
9698 if(enable == TRUE)
9699 strcpy(string,"1");
9700 else
9701 strcpy(string,"0");
9702
9703 params.name = "ap_isolate";
9704 params.value = string;
9705
9706 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9707 wifi_hostapdWrite(config_file,&params,1);
9708 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9709
9710 return RETURN_OK;
9711}
9712
9713INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9714{
9715 if (NULL == output_dBm)
9716 return RETURN_ERR;
9717
9718 *output_dBm = 0;
9719 return RETURN_OK;
9720}
9721
9722INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9723{
9724 return RETURN_OK;
9725}
9726INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9727{
9728 return RETURN_OK;
9729}
9730INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9731{
9732 return RETURN_OK;
9733}
9734INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9735{
9736 return RETURN_OK;
9737}
9738INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9739{
9740 return RETURN_OK;
9741}
9742INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9743{
9744 char config_file[MAX_BUF_SIZE] = {0};
9745 struct params list;
9746
9747 list.name = "bss_transition";
9748 list.value = activate?"1":"0";
9749 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9750 wifi_hostapdWrite(config_file, &list, 1);
9751
9752 return RETURN_OK;
9753}
9754wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9755
9756void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9757{
9758 return;
9759}
9760
9761INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9762{
9763 // TODO Implement me!
9764 return RETURN_OK;
9765}
9766
9767INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9768{
developera3c68b92022-09-13 15:27:29 +08009769 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009770 FILE *f = NULL;
9771
developer72ec5572023-01-05 16:27:13 +08009772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009773
developer72ec5572023-01-05 16:27:13 +08009774 if (essid == NULL)
9775 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009776
developer72ec5572023-01-05 16:27:13 +08009777 if (strlen(essid) == 0 || apIndex == -1) {
9778 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9779 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009780 }
9781
developer72ec5572023-01-05 16:27:13 +08009782 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9783 f = fopen(file_name, "w");
9784 if (f == NULL)
9785 return RETURN_ERR;
9786
9787 // For mode == 0 is to disable filter, just don't write ssid to the file.
9788 fprintf(f, "%d\n%s", mode, mode?essid:"");
9789 fclose(f);
9790 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009791 return RETURN_OK;
9792}
9793
9794INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9795{
9796 // TODO Implement me!
9797 //Apply wifi_pushRadioChannel() instantly
9798 return RETURN_ERR;
9799}
9800
9801INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9802{
9803 // TODO Implement me!
9804 return RETURN_OK;
9805}
9806
9807#ifdef HAL_NETLINK_IMPL
9808static int tidStats_callback(struct nl_msg *msg, void *arg) {
9809 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9810 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9811 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9812 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9813 int rem , tid_index = 0;
9814
9815 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9816 wifi_associated_dev_tid_entry_t *stats_entry;
9817
9818 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9819 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9820 };
9821 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9822 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9823 };
9824
9825 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9826 genlmsg_attrlen(gnlh, 0), NULL);
9827
9828
9829 if (!tb[NL80211_ATTR_STA_INFO]) {
9830 fprintf(stderr, "station stats missing!\n");
9831 return NL_SKIP;
9832 }
9833
9834 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9835 tb[NL80211_ATTR_STA_INFO],
9836 stats_policy)) {
9837 fprintf(stderr, "failed to parse nested attributes!\n");
9838 return NL_SKIP;
9839 }
9840
9841 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9842 {
9843 stats_entry = &out->tid_array[tid_index];
9844
9845 stats_entry->tid = tid_index;
9846 stats_entry->ac = _tid_ac_index_get[tid_index];
9847
9848 if(sinfo[NL80211_STA_INFO_TID_STATS])
9849 {
9850 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9851 printf("failed to parse nested stats attributes!");
9852 return NL_SKIP;
9853 }
9854 }
9855 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9856 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9857
9858 if(tid_index < (PS_MAX_TID - 1))
9859 tid_index++;
9860 }
9861 //ToDo: sum_time_ms, ewma_time_ms
9862 return NL_SKIP;
9863}
9864#endif
9865
9866INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9867{
9868#ifdef HAL_NETLINK_IMPL
9869 Netlink nl;
9870 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009871 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009872
developerac6f1142022-12-20 19:26:35 +08009873 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009874 return RETURN_ERR;
9875
9876 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009877
9878 nl.id = initSock80211(&nl);
9879
9880 if (nl.id < 0) {
9881 fprintf(stderr, "Error initializing netlink \n");
9882 return -1;
9883 }
9884
9885 struct nl_msg* msg = nlmsg_alloc();
9886
9887 if (!msg) {
9888 fprintf(stderr, "Failed to allocate netlink message.\n");
9889 nlfree(&nl);
9890 return -2;
9891 }
9892
9893 genlmsg_put(msg,
9894 NL_AUTO_PORT,
9895 NL_AUTO_SEQ,
9896 nl.id,
9897 0,
9898 0,
9899 NL80211_CMD_GET_STATION,
9900 0);
9901
9902 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9903 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9904 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9905 nl_send_auto(nl.socket, msg);
9906 nl_recvmsgs(nl.socket, nl.cb);
9907 nlmsg_free(msg);
9908 nlfree(&nl);
9909 return RETURN_OK;
9910#else
9911//iw implementation
9912#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9913#define TOTAL_MAX_LINES 50
9914
9915 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009916 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009917 FILE *fp=NULL;
9918 char pipeCmd[1024]= {'\0'};
9919 int lines,tid_index=0;
9920 char mac_addr[20] = {'\0'};
9921
developerac6f1142022-12-20 19:26:35 +08009922 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009923 return RETURN_ERR;
9924
developer06a01d92022-09-07 16:32:39 +08009925 wifi_associated_dev_tid_entry_t *stats_entry;
9926
developer06a01d92022-09-07 16:32:39 +08009927 strcpy(mac_addr,clientMacAddress);
9928
9929 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9930 fp= popen(pipeCmd,"r");
9931 if(fp == NULL)
9932 {
9933 perror("popen for station dump failed\n");
9934 return RETURN_ERR;
9935 }
9936 pclose(fp);
9937
9938 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9939 fp=popen(pipeCmd,"r");
9940 if(fp == NULL)
9941 {
9942 perror("popen for grep station failed\n");
9943 return RETURN_ERR;
9944 }
9945 else if(fgets(buf,sizeof(buf),fp) != NULL)
9946 lines=atoi(buf);
9947 else
9948 {
9949 pclose(fp);
9950 fprintf(stderr,"No devices are connected \n");
9951 return RETURN_ERR;
9952 }
9953 pclose(fp);
9954
9955 if(lines == 1)
9956 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9957
9958 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9959 {
9960 stats_entry = &tid_stats->tid_array[tid_index];
9961 stats_entry->tid = tid_index;
9962
9963 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);
9964
9965 fp=popen(pipeCmd,"r");
9966 if(fp ==NULL)
9967 {
9968 perror("Failed to read from tid file \n");
9969 return RETURN_ERR;
9970 }
9971 else if(fgets(buf,sizeof(buf),fp) != NULL)
9972 stats_entry->num_msdus = atol(buf);
9973
9974 pclose(fp);
9975 stats_entry->ac = _tid_ac_index_get[tid_index];
9976// TODO:
9977// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9978// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9979 }
9980 return RETURN_OK;
9981#endif
9982}
9983
9984
9985INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9986{
developerd946fd62022-12-08 18:03:28 +08009987 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009988 char cmd[128]={0};
9989 char buf[128]={0};
9990 int freq = 0;
9991
9992 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9993
9994 // full mode is used to scan all channels.
9995 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9996 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9997 ieee80211_channel_to_frequency(chan_list[0], &freq);
9998
developerac6f1142022-12-20 19:26:35 +08009999 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010000 return RETURN_ERR;
10001
developer615510b2022-09-27 10:14:35 +080010002 if (freq)
developerd946fd62022-12-08 18:03:28 +080010003 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +080010004 else
developerd946fd62022-12-08 18:03:28 +080010005 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +080010006
10007 _syscmd(cmd, buf, sizeof(buf));
10008 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10009
developer06a01d92022-09-07 16:32:39 +080010010 return RETURN_OK;
10011}
10012
10013
10014INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10015{
10016 // TODO Implement me!
10017 return RETURN_ERR;
10018}
10019
10020INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10021{
10022 // TODO Implement me!
10023 return RETURN_ERR;
10024}
10025
10026INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10027{
10028 // TODO Implement me!
10029 return RETURN_ERR;
10030}
10031
10032INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10033{
10034 // TODO Implement me!
10035 return RETURN_ERR;
10036}
10037
10038INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10039{
10040 // TODO Implement me!
10041 return RETURN_ERR;
10042}
10043
10044INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10045{
10046 // TODO Implement me!
10047 return RETURN_ERR;
10048}
10049
10050INT wifi_steering_eventUnregister(void)
10051{
10052 // TODO Implement me!
10053 return RETURN_ERR;
10054}
10055
10056INT wifi_delApAclDevices(INT apIndex)
10057{
10058#if 0
10059 char cmd[MAX_BUF_SIZE] = {0};
10060 char buf[MAX_BUF_SIZE] = {0};
10061
10062 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010063 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010064 if(_syscmd(cmd,buf,sizeof(buf)))
10065 return RETURN_ERR;
10066#endif
developer9988c232023-03-06 14:57:08 +080010067 char cmd[256]={0};
10068 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010069
developere6aafda2022-09-13 14:59:28 +080010070 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010071 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 +080010072 if(_syscmd(cmd, buf, sizeof(buf)))
10073 return RETURN_ERR;
10074 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010075
10076 return RETURN_OK;
10077}
10078
10079#ifdef HAL_NETLINK_IMPL
10080static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10081 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10082 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10083 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10084 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10085 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10086 char mac_addr[20],dev[20];
10087
10088 nla_parse(tb,
10089 NL80211_ATTR_MAX,
10090 genlmsg_attrdata(gnlh, 0),
10091 genlmsg_attrlen(gnlh, 0),
10092 NULL);
10093
10094 if(!tb[NL80211_ATTR_STA_INFO]) {
10095 fprintf(stderr, "sta stats missing!\n");
10096 return NL_SKIP;
10097 }
10098
10099 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10100 fprintf(stderr, "failed to parse nested attributes!\n");
10101 return NL_SKIP;
10102 }
10103 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10104
10105 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10106
10107 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10108 fprintf(stderr, "failed to parse nested rate attributes!");
10109 return NL_SKIP;
10110 }
10111
10112 if(sinfo[NL80211_STA_INFO_TID_STATS])
10113 {
10114 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10115 printf("failed to parse nested stats attributes!");
10116 return NL_SKIP;
10117 }
10118 }
10119
10120 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10121 {
10122 printf("Type is VHT\n");
10123 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10124 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10125
10126 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10127 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10128 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10129 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10130 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10131 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10132 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10133 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10134 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10135 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10136 }
10137 else
10138 {
10139 printf(" OFDM or CCK \n");
10140 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10141 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10142 }
10143
10144 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10145 if(rinfo[NL80211_RATE_INFO_MCS])
10146 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10147 }
10148 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10149 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10150 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10151 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10152
10153 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10154 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10155
10156 if (sinfo[NL80211_STA_INFO_SIGNAL])
10157 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10158 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10159 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10160 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10161 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10162 //rssi_array need to be filled
10163 return NL_SKIP;
10164}
10165#endif
10166
10167INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10168{
10169#ifdef HAL_NETLINK_IMPL
10170 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010171 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010172 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010173 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010174
10175 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10176
10177 if (*output_array_size <= 0)
10178 return RETURN_OK;
10179
developer06a01d92022-09-07 16:32:39 +080010180 nl.id = initSock80211(&nl);
10181
10182 if (nl.id < 0) {
10183 fprintf(stderr, "Error initializing netlink \n");
10184 return 0;
10185 }
10186
10187 struct nl_msg* msg = nlmsg_alloc();
10188
10189 if (!msg) {
10190 fprintf(stderr, "Failed to allocate netlink message.\n");
10191 nlfree(&nl);
10192 return 0;
10193 }
10194
10195 genlmsg_put(msg,
10196 NL_AUTO_PORT,
10197 NL_AUTO_SEQ,
10198 nl.id,
10199 0,
10200 0,
10201 NL80211_CMD_GET_STATION,
10202 0);
10203
10204 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10205 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10206 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10207 nl_send_auto(nl.socket, msg);
10208 nl_recvmsgs(nl.socket, nl.cb);
10209 nlmsg_free(msg);
10210 nlfree(&nl);
10211 return RETURN_OK;
10212#else
10213 //TODO Implement me
10214 return RETURN_OK;
10215#endif
10216}
10217
10218#ifdef HAL_NETLINK_IMPL
10219static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10220 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10221 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10222 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10223 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10224 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10225 char mac_addr[20],dev[20];
10226
10227 nla_parse(tb,
10228 NL80211_ATTR_MAX,
10229 genlmsg_attrdata(gnlh, 0),
10230 genlmsg_attrlen(gnlh, 0),
10231 NULL);
10232
10233 if(!tb[NL80211_ATTR_STA_INFO]) {
10234 fprintf(stderr, "sta stats missing!\n");
10235 return NL_SKIP;
10236 }
10237
10238 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10239 fprintf(stderr, "failed to parse nested attributes!\n");
10240 return NL_SKIP;
10241 }
10242
10243 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10244
10245 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10246
10247 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10248 fprintf(stderr, "failed to parse nested rate attributes!");
10249 return NL_SKIP;
10250 }
10251
10252 if(sinfo[NL80211_STA_INFO_TID_STATS])
10253 {
10254 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10255 printf("failed to parse nested stats attributes!");
10256 return NL_SKIP;
10257 }
10258 }
10259 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10260 {
10261 printf("Type is VHT\n");
10262 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10263 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10264
10265 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10266 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10267 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10268 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10269 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10270 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10271 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10272 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10273 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10274 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10275 }
10276 else
10277 {
10278 printf(" OFDM or CCK \n");
10279 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10280 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10281 }
10282
10283 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10284 if(rinfo[NL80211_RATE_INFO_MCS])
10285 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10286 }
10287
10288 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10289 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10290 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10291 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10292
10293 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10294 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10295 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10296
10297 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10298 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10299
10300 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10301 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10302
10303 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10304 ((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]);
10305
10306 return NL_SKIP;
10307}
10308#endif
10309
10310INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10311{
10312#ifdef HAL_NETLINK_IMPL
10313 Netlink nl;
10314 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010315 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010316 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010317 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010318
10319 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10320
10321 if (*output_array_size <= 0)
10322 return RETURN_OK;
10323
developerd946fd62022-12-08 18:03:28 +080010324 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010325
10326 nl.id = initSock80211(&nl);
10327
10328 if(nl.id < 0) {
10329 fprintf(stderr, "Error initializing netlink \n");
10330 return 0;
10331 }
10332
10333 struct nl_msg* msg = nlmsg_alloc();
10334
10335 if(!msg) {
10336 fprintf(stderr, "Failed to allocate netlink message.\n");
10337 nlfree(&nl);
10338 return 0;
10339 }
10340
10341 genlmsg_put(msg,
10342 NL_AUTO_PORT,
10343 NL_AUTO_SEQ,
10344 nl.id,
10345 0,
10346 0,
10347 NL80211_CMD_GET_STATION,
10348 0);
10349
10350 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10351 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10352 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10353 nl_send_auto(nl.socket, msg);
10354 nl_recvmsgs(nl.socket, nl.cb);
10355 nlmsg_free(msg);
10356 nlfree(&nl);
10357 return RETURN_OK;
10358#else
10359 //TODO Implement me
10360 return RETURN_OK;
10361#endif
10362}
10363
10364INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10365{
10366 // TODO Implement me!
10367 char buf[MAX_BUF_SIZE] = {0};
10368 char config_file[MAX_BUF_SIZE] = {0};
10369
10370 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10371 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10372 *activate = (strncmp("1",buf,1) == 0);
10373
10374 return RETURN_OK;
10375}
10376
10377INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10378{
10379 char config_file[MAX_BUF_SIZE] = {0};
10380 struct params list;
10381
10382 list.name = "rrm_neighbor_report";
10383 list.value = activate?"1":"0";
10384 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10385 wifi_hostapdWrite(config_file, &list, 1);
10386
10387 return RETURN_OK;
10388}
10389
10390INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10391{
10392 char buf[32] = {0};
10393 char config_file[MAX_BUF_SIZE] = {0};
10394
10395 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10396 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10397 *activate = (strncmp("1",buf,1) == 0);
10398
10399 return RETURN_OK;
10400}
10401#undef HAL_NETLINK_IMPL
10402#ifdef HAL_NETLINK_IMPL
10403static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10404 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10405 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10406 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10407 char dev[20];
10408 int freq =0 ;
10409 static int i=0;
10410
10411 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10412
10413 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10414 };
10415
10416 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10417
10418 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10419
10420 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10421 fprintf(stderr, "survey data missing!\n");
10422 return NL_SKIP;
10423 }
10424
10425 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10426 {
10427 fprintf(stderr, "failed to parse nested attributes!\n");
10428 return NL_SKIP;
10429 }
10430
10431
10432 if(out[0].array_size == 1 )
10433 {
10434 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10435 {
10436 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10437 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10438 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10439
10440 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10441 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10442 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10443 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10444 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10445 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10446 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10447 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10448 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10449 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10450 if (sinfo[NL80211_SURVEY_INFO_TIME])
10451 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10452 return NL_STOP;
10453 }
10454 }
10455 else
10456 {
10457 if ( i <= out[0].array_size )
10458 {
10459 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10460 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10461 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10462
10463 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10464 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10465 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10466 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10467 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10468 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10469 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10470 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10471 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10472 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10473 if (sinfo[NL80211_SURVEY_INFO_TIME])
10474 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10475 }
10476 }
10477
10478 i++;
10479 return NL_SKIP;
10480}
10481#endif
10482
10483static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10484{
10485 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10486 FILE *fp;
10487
10488 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10489 {
10490 printf("Creating Frequency-Channel Map\n");
10491 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10492 }
10493 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10494 if((fp = popen(command, "r")))
10495 {
10496 fgets(output, sizeof(output), fp);
10497 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010498 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010499 }
10500
10501 return 0;
10502}
10503
10504static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10505{
10506 int freqMHz = -1;
10507 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010508 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010509
10510 ieee80211_channel_to_frequency(channel, &freqMHz);
10511 if (freqMHz == -1) {
10512 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10513 return -1;
10514 }
10515
developer7930d352022-12-21 17:55:42 +080010516 wifi_GetInterfaceName(radioIndex, interface_name);
10517 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010518 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10519 radioIndex, freqMHz);
10520 return -1;
10521 }
10522
10523 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10524 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10525 return -1;
10526 }
10527
10528 return 0;
10529}
10530
10531static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10532{
10533 const char *ptr = buf;
10534 char *key = NULL;
10535 char *val = NULL;
10536 char line[256] = { '\0' };
10537
10538 while (ptr = get_line_from_str_buf(ptr, line)) {
10539 if (strstr(line, "Frequency")) continue;
10540
10541 key = strtok(line, ":");
10542 val = strtok(NULL, " ");
10543 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10544
10545 if (!strcmp(key, "noise")) {
10546 sscanf(val, "%d", &stats->ch_noise);
10547 if (stats->ch_noise == 0) {
10548 // Workaround for missing noise information.
10549 // Assume -95 for 2.4G and -103 for 5G
10550 if (radioIndex == 0) stats->ch_noise = -95;
10551 if (radioIndex == 1) stats->ch_noise = -103;
10552 }
10553 }
10554 else if (!strcmp(key, "channel active time")) {
10555 sscanf(val, "%llu", &stats->ch_utilization_total);
10556 }
10557 else if (!strcmp(key, "channel busy time")) {
10558 sscanf(val, "%llu", &stats->ch_utilization_busy);
10559 }
10560 else if (!strcmp(key, "channel receive time")) {
10561 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10562 }
10563 else if (!strcmp(key, "channel transmit time")) {
10564 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10565 }
10566 };
10567
10568 return 0;
10569}
10570
10571INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10572{
10573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10574#ifdef HAL_NETLINK_IMPL
10575 Netlink nl;
10576 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010577 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010578
10579 local[0].array_size = array_size;
10580
developerac6f1142022-12-20 19:26:35 +080010581 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010582 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010583
10584 nl.id = initSock80211(&nl);
10585
10586 if (nl.id < 0) {
10587 fprintf(stderr, "Error initializing netlink \n");
10588 return -1;
10589 }
10590
10591 struct nl_msg* msg = nlmsg_alloc();
10592
10593 if (!msg) {
10594 fprintf(stderr, "Failed to allocate netlink message.\n");
10595 nlfree(&nl);
10596 return -2;
10597 }
10598
10599 genlmsg_put(msg,
10600 NL_AUTO_PORT,
10601 NL_AUTO_SEQ,
10602 nl.id,
10603 0,
10604 NLM_F_DUMP,
10605 NL80211_CMD_GET_SURVEY,
10606 0);
10607
10608 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10609 nl_send_auto(nl.socket, msg);
10610 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10611 nl_recvmsgs(nl.socket, nl.cb);
10612 nlmsg_free(msg);
10613 nlfree(&nl);
10614 //Copying the Values
10615 for(int i=0;i<array_size;i++)
10616 {
10617 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10618 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10619 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10620 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10621 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10622 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10623 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10624 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10625 }
10626#else
10627 ULONG channel = 0;
10628 int i;
10629 int number_of_channels = array_size;
10630 char buf[512];
10631 INT ret;
10632 wifi_channelStats_t tmp_stats;
10633
10634 if (number_of_channels == 0) {
10635 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10636 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10637 return RETURN_ERR;
10638 }
10639 number_of_channels = 1;
10640 input_output_channelStats_array[0].ch_number = channel;
10641 }
10642
10643 for (i = 0; i < number_of_channels; i++) {
10644
10645 input_output_channelStats_array[i].ch_noise = 0;
10646 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10647 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10648 input_output_channelStats_array[i].ch_utilization_busy = 0;
10649 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10650 input_output_channelStats_array[i].ch_utilization_total = 0;
10651
10652 memset(buf, 0, sizeof(buf));
10653 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10654 return RETURN_ERR;
10655 }
10656 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10657 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10658 return RETURN_ERR;
10659 }
10660
10661 // XXX: fake missing 'self' counter which is not available in iw survey output
10662 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10663 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10664
10665 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10666 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10667 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10668 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10669 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10670
10671 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",
10672 __func__,
10673 input_output_channelStats_array[i].ch_number,
10674 input_output_channelStats_array[i].ch_noise,
10675 input_output_channelStats_array[i].ch_utilization_total,
10676 input_output_channelStats_array[i].ch_utilization_busy,
10677 input_output_channelStats_array[i].ch_utilization_busy_rx,
10678 input_output_channelStats_array[i].ch_utilization_busy_tx,
10679 input_output_channelStats_array[i].ch_utilization_busy_self,
10680 input_output_channelStats_array[i].ch_utilization_busy_ext);
10681 }
10682#endif
10683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10684 return RETURN_OK;
10685}
10686#define HAL_NETLINK_IMPL
10687
10688/* Hostapd events */
10689
10690#ifndef container_of
10691#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10692#define container_of(ptr, type, member) \
10693 ((type *)((char *)ptr - offset_of(type, member)))
10694#endif /* container_of */
10695
10696struct ctrl {
10697 char sockpath[128];
10698 char sockdir[128];
10699 char bss[IFNAMSIZ];
10700 char reply[4096];
10701 int ssid_index;
10702 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10703 void (*overrun)(struct ctrl *ctrl);
10704 struct wpa_ctrl *wpa;
10705 unsigned int ovfl;
10706 size_t reply_len;
10707 int initialized;
10708 ev_timer retry;
10709 ev_timer watchdog;
10710 ev_stat stat;
10711 ev_io io;
10712};
10713static wifi_newApAssociatedDevice_callback clients_connect_cb;
10714static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10715static struct ctrl wpa_ctrl[MAX_APS];
10716static int initialized;
10717
10718static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10719{
10720 char cbuf[256] = {};
10721 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10722 struct cmsghdr *cmsg;
10723 unsigned int ovfl = ctrl->ovfl;
10724 unsigned int drop;
10725
10726 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10727 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10728 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10729 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10730
10731 drop = ovfl - ctrl->ovfl;
10732 ctrl->ovfl = ovfl;
10733
10734 return drop;
10735}
10736
10737static void ctrl_close(struct ctrl *ctrl)
10738{
10739 if (ctrl->io.cb)
10740 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10741 if (ctrl->retry.cb)
10742 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10743 if (!ctrl->wpa)
10744 return;
10745
10746 wpa_ctrl_detach(ctrl->wpa);
10747 wpa_ctrl_close(ctrl->wpa);
10748 ctrl->wpa = NULL;
10749 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10750}
10751
10752static void ctrl_process(struct ctrl *ctrl)
10753{
10754 const char *str;
10755 int drops;
10756 int level;
10757 int err;
10758
10759 /* Example events:
10760 *
10761 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10762 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10763 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10764 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10765 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10766 */
10767 if (!(str = index(ctrl->reply, '>')))
10768 return;
10769 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10770 return;
10771
10772 str++;
10773
10774 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10775 if (!(str = index(ctrl->reply, ' ')))
10776 return;
10777 wifi_associated_dev_t sta;
10778 memset(&sta, 0, sizeof(sta));
10779
10780 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10781 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10782 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10783
10784 sta.cli_Active=true;
10785
10786 (clients_connect_cb)(ctrl->ssid_index, &sta);
10787 goto handled;
10788 }
10789
10790 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10791 if (!(str = index(ctrl->reply, ' ')))
10792 return;
10793
10794 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10795 goto handled;
10796 }
10797
10798 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10799 printf("CTRL_WPA: handle TERMINATING event\n");
10800 goto retry;
10801 }
10802
10803 if (strncmp("AP-DISABLED", str, 11) == 0) {
10804 printf("CTRL_WPA: handle AP-DISABLED\n");
10805 goto retry;
10806 }
10807
10808 printf("Event not supported!!\n");
10809
10810handled:
10811
10812 if ((drops = ctrl_get_drops(ctrl))) {
10813 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10814 if (ctrl->overrun)
10815 ctrl->overrun(ctrl);
10816 }
10817
10818 return;
10819
10820retry:
10821 printf("WPA_CTRL: closing\n");
10822 ctrl_close(ctrl);
10823 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10824 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10825}
10826
10827static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10828{
10829 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10830 int err;
10831
10832 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10833 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10834 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10835 ctrl->reply[ctrl->reply_len] = 0;
10836 if (err < 0) {
10837 if (errno == EAGAIN || errno == EWOULDBLOCK)
10838 return;
10839 ctrl_close(ctrl);
10840 ev_timer_again(EV_A_ &ctrl->retry);
10841 return;
10842 }
10843
10844 ctrl_process(ctrl);
10845}
10846
10847static int ctrl_open(struct ctrl *ctrl)
10848{
10849 int fd;
10850
10851 if (ctrl->wpa)
10852 return 0;
10853
10854 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10855 if (!ctrl->wpa)
10856 goto err;
10857
10858 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10859 goto err_close;
10860
10861 fd = wpa_ctrl_get_fd(ctrl->wpa);
10862 if (fd < 0)
10863 goto err_detach;
10864
10865 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10866 goto err_detach;
10867
10868 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10869 ev_io_start(EV_DEFAULT_ &ctrl->io);
10870
10871 return 0;
10872
10873err_detach:
10874 wpa_ctrl_detach(ctrl->wpa);
10875err_close:
10876 wpa_ctrl_close(ctrl->wpa);
10877err:
10878 ctrl->wpa = NULL;
10879 return -1;
10880}
10881
10882static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10883{
10884 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10885
10886 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10887 ctrl_open(ctrl);
10888}
10889
10890static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10891{
10892 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10893
10894 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10895 if (ctrl_open(ctrl) == 0) {
10896 printf("WPA_CTRL: retry successful\n");
10897 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10898 }
10899}
10900
10901int ctrl_enable(struct ctrl *ctrl)
10902{
10903 if (ctrl->wpa)
10904 return 0;
10905
10906 if (!ctrl->stat.cb) {
10907 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10908 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10909 }
10910
10911 if (!ctrl->retry.cb) {
10912 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10913 }
10914
10915 return ctrl_open(ctrl);
10916}
10917
10918static void
10919ctrl_msg_cb(char *buf, size_t len)
10920{
10921 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10922
10923 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10924 ctrl_process(ctrl);
10925}
10926
10927static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10928{
10929 int err;
10930
10931 if (!ctrl->wpa)
10932 return -1;
10933 if (*reply_len < 2)
10934 return -1;
10935
10936 (*reply_len)--;
10937 ctrl->reply_len = sizeof(ctrl->reply);
10938 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10939 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10940 if (err < 0)
10941 return err;
10942
10943 if (ctrl->reply_len > *reply_len)
10944 ctrl->reply_len = *reply_len;
10945
10946 *reply_len = ctrl->reply_len;
10947 memcpy(reply, ctrl->reply, *reply_len);
10948 reply[*reply_len - 1] = 0;
10949 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10950 return 0;
10951}
10952
10953static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10954{
10955 const char *pong = "PONG";
10956 const char *ping = "PING";
10957 char reply[1024];
10958 size_t len = sizeof(reply);
10959 int err;
10960 ULONG s, snum;
10961 INT ret;
10962 BOOL status;
10963
10964 printf("WPA_CTRL: watchdog cb\n");
10965
10966 ret = wifi_getSSIDNumberOfEntries(&snum);
10967 if (ret != RETURN_OK) {
10968 printf("%s: failed to get SSID count", __func__);
10969 return;
10970 }
10971
10972 if (snum > MAX_APS) {
10973 printf("more ssid than supported! %lu\n", snum);
10974 return;
10975 }
10976
10977 for (s = 0; s < snum; s++) {
10978 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010979 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010980 continue;
10981 }
10982 if (status == false) continue;
10983
10984 memset(reply, 0, sizeof(reply));
10985 len = sizeof(reply);
10986 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10987 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10988 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10989 continue;
10990
10991 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10992 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010993 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010994 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10995 }
10996}
10997
10998static int init_wpa()
10999{
11000 int ret = 0, i = 0;
11001 ULONG s, snum;
11002
11003 ret = wifi_getSSIDNumberOfEntries(&snum);
11004 if (ret != RETURN_OK) {
11005 printf("%s: failed to get SSID count", __func__);
11006 return RETURN_ERR;
11007 }
11008
11009 if (snum > MAX_APS) {
11010 printf("more ssid than supported! %lu\n", snum);
11011 return RETURN_ERR;
11012 }
11013
11014 for (s = 0; s < snum; s++) {
11015 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11016 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11017 wpa_ctrl[s].ssid_index = s;
11018 ctrl_enable(&wpa_ctrl[s]);
11019 }
11020
11021 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11022 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11023
11024 initialized = 1;
11025 printf("WPA_CTRL: initialized\n");
11026
11027 return RETURN_OK;
11028}
11029
11030void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11031{
11032 clients_connect_cb = callback_proc;
11033 if (!initialized)
11034 init_wpa();
11035}
11036
11037void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11038{
11039 clients_disconnect_cb = callback_proc;
11040 if (!initialized)
11041 init_wpa();
11042}
11043
11044INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11045{
11046 // TODO Implement me!
11047 return RETURN_ERR;
11048}
11049
11050INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11051{
11052 // TODO Implement me!
11053 return RETURN_ERR;
11054}
11055
11056INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11057{
11058 int i;
developer4b102122023-02-15 10:53:03 +080011059 int phyId = -1;
11060 char cmd[256] = {0};
11061 char channel_numbers_buf[256] = {0};
11062 char dfs_state_buf[256] = {0};
11063 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011064 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011065 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080011066
developer4b102122023-02-15 10:53:03 +080011067 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011068
developer4b102122023-02-15 10:53:03 +080011069 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11070 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011071
developer4b102122023-02-15 10:53:03 +080011072 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 +080011073
developer4b102122023-02-15 10:53:03 +080011074 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11075 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11076 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011077 }
11078
developer4b102122023-02-15 10:53:03 +080011079 ptr = channel_numbers_buf;
11080 i = 0;
11081 while (ptr = get_line_from_str_buf(ptr, line)) {
11082 if (i >= outputMapSize) {
11083 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11084 return RETURN_ERR;
11085 }
11086 sscanf(line, "%d", &outputMap[i].ch_number);
11087
11088 memset(cmd, 0, sizeof(cmd));
11089 // Below command should fetch string for DFS state (usable, available or unavailable)
11090 // Example line: "DFS state: usable (for 78930 sec)"
11091 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) {
11092 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011093 return RETURN_ERR;
11094 }
11095
developer4b102122023-02-15 10:53:03 +080011096 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11097 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011098 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11099 return RETURN_ERR;
11100 }
11101
developer4b102122023-02-15 10:53:03 +080011102 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011103
developer4b102122023-02-15 10:53:03 +080011104 if (!strcmp(dfs_state_buf, "usable")) {
11105 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11106 } else if (!strcmp(dfs_state_buf, "available")) {
11107 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11108 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11109 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11110 } else {
11111 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011112 }
developer4b102122023-02-15 10:53:03 +080011113 i++;
developer06a01d92022-09-07 16:32:39 +080011114 }
11115
developer4b102122023-02-15 10:53:03 +080011116 return RETURN_OK;
11117
developer06a01d92022-09-07 16:32:39 +080011118 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11119 return RETURN_ERR;
11120}
11121
11122INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11123{
11124 // TODO Implement me!
11125 return RETURN_ERR;
11126}
11127
11128INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11129{
11130 return RETURN_OK;
11131}
11132
11133INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11134{
11135 // TODO Implement me!
11136 return RETURN_ERR;
11137}
11138
11139INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11140{
11141 // TODO API refrence Implementaion is present on RPI hal
11142 return RETURN_ERR;
11143}
11144
developerfeab1d12023-09-27 11:29:38 +080011145
developer06a01d92022-09-07 16:32:39 +080011146INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11147{
developera5005b62022-09-13 15:43:35 +080011148 char cmd[128]={'\0'};
11149 char buf[128]={'\0'};
developerfeab1d12023-09-27 11:29:38 +080011150 int radioIndex = -1;
11151 int phyIndex = -1;
11152 bool enabled = false;
11153 int cur_tx_dbm = 0;
developera5005b62022-09-13 15:43:35 +080011154
11155 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfeab1d12023-09-27 11:29:38 +080011156
developera5005b62022-09-13 15:43:35 +080011157 if(txpwr_pcntg == NULL)
11158 return RETURN_ERR;
11159
developerfeab1d12023-09-27 11:29:38 +080011160 // The API name as getRadioXXX, I think the input index should be radioIndex,
11161 // but current we not change the name, but use it as radioIndex
11162 radioIndex = apIndex;
11163 phyIndex = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +080011164
developera5005b62022-09-13 15:43:35 +080011165 // Get the maximum tx power of the device
developerfeab1d12023-09-27 11:29:38 +080011166 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11167 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011168 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011169 if (strcmp(buf, "enable") == 0)
11170 enabled = true;
developera5005b62022-09-13 15:43:35 +080011171
developerfeab1d12023-09-27 11:29:38 +080011172 if (!enabled) {
11173 *txpwr_pcntg = 100;
11174 return RETURN_OK;
11175 }
11176
developera5005b62022-09-13 15:43:35 +080011177 memset(cmd, 0, sizeof(cmd));
11178 memset(buf, 0, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011179 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11180 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011181 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011182 cur_tx_dbm = strtol(buf, NULL, 10);
developera5005b62022-09-13 15:43:35 +080011183
developerfeab1d12023-09-27 11:29:38 +080011184 switch (cur_tx_dbm) {
11185 case 0:
11186 *txpwr_pcntg = 100; // range 91-100
developera5005b62022-09-13 15:43:35 +080011187 break;
developerfeab1d12023-09-27 11:29:38 +080011188 case 1:
11189 *txpwr_pcntg = 75; // range 61-90
11190 break;
11191 case 3:
11192 *txpwr_pcntg = 50; // range 31-60
11193 break;
11194 case 6:
11195 *txpwr_pcntg = 25; // range 16-30
11196 break;
11197 case 9:
11198 *txpwr_pcntg = 12; // range 10-15
11199 break;
11200 case 12:
11201 *txpwr_pcntg = 6; // range 1-9
11202 break;
11203 default:
11204 *txpwr_pcntg = 100; // 0
developera5005b62022-09-13 15:43:35 +080011205 }
developerfeab1d12023-09-27 11:29:38 +080011206
developer06a01d92022-09-07 16:32:39 +080011207 return RETURN_OK;
11208}
11209
11210INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11211{
developer58599c22022-09-13 16:40:34 +080011212 // TODO precac feature.
11213 struct params params = {0};
11214 char config_file[128] = {0};
11215
11216 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11217
11218 params.name = "enable_background_radar";
11219 params.value = enable?"1":"0";
11220 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11221 wifi_hostapdWrite(config_file, &params, 1);
11222 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11223
11224 /* TODO precac feature */
11225
11226 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11227 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011228}
11229
11230INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11231{
developer58599c22022-09-13 16:40:34 +080011232 char config_file[128] = {0};
11233 char buf[64] = {0};
11234
11235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11236 if (NULL == enable || NULL == precac)
11237 return RETURN_ERR;
11238
11239 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11240 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011241 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011242 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011243 *precac = true;
11244 } else {
developer58599c22022-09-13 16:40:34 +080011245 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011246 *precac = false;
11247 }
developer58599c22022-09-13 16:40:34 +080011248
11249 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11250 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011251}
11252
11253INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11254{
developer58599c22022-09-13 16:40:34 +080011255 *supported = TRUE;
11256 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011257}
11258
developera7149722023-01-11 11:36:21 +080011259bool check_is_hemu_vendor_new_patch() {
11260 char cmd[128] = {0};
11261 char buf[128] = {0};
11262
11263 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11264 _syscmd(cmd, buf, sizeof(buf));
11265
11266 if (strlen(buf) > 0)
11267 return FALSE;
11268 else
11269 return TRUE;
11270}
11271
developer3e6b1692022-09-30 18:04:05 +080011272INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11273{
11274 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11275 struct params params = {0};
11276 char config_file[64] = {0};
11277 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011278 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011279 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011280 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011281 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11282
developera7149722023-01-11 11:36:21 +080011283 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011284
11285 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11286 set_mu_type &= ~0x05; // unset bit 0, 2
11287 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11288 set_mu_type |= 0x01;
11289 set_mu_type &= ~0x04;
11290 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11291 set_mu_type &= ~0x01;
11292 set_mu_type |= 0x04;
11293 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11294 set_mu_type |= 0x05; // set bit 0, 2
11295 }
11296
developera7149722023-01-11 11:36:21 +080011297 new_vendor_patch = check_is_hemu_vendor_new_patch();
11298 if (new_vendor_patch)
11299 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11300 else
11301 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11302
11303 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011304 sprintf(buf, "%u", set_mu_type);
11305 params.value = buf;
11306 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11307 wifi_hostapdWrite(config_file, &params, 1);
11308 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011309 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011310
11311 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11312 return RETURN_OK;
11313}
11314
11315INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11316{
11317 struct params params={0};
11318 char config_file[64] = {0};
11319 char buf[64] = {0};
11320 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011321 bool new_vendor_patch = FALSE;
11322 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011323
11324 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11325
11326 if (mu_type == NULL)
11327 return RETURN_ERR;
11328
developera7149722023-01-11 11:36:21 +080011329 new_vendor_patch = check_is_hemu_vendor_new_patch();
11330
11331 if (new_vendor_patch)
11332 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11333 else
11334 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11335
developer3e6b1692022-09-30 18:04:05 +080011336 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011337 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011338 get_mu_type = strtol(buf, NULL, 10);
11339
11340 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11341 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11342 else if (get_mu_type & 0x04)
11343 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11344 else if (get_mu_type & 0x01)
11345 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11346 else
11347 *mu_type = WIFI_DL_MU_TYPE_NONE;
11348
11349 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11350 return RETURN_OK;
11351}
11352
11353INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11354{
11355 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11356 struct params params={0};
11357 char config_file[64] = {0};
11358 char buf[64] = {0};
11359 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011360 bool new_vendor_patch = FALSE;
11361 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011362 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11363
developera7149722023-01-11 11:36:21 +080011364 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011365
11366 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11367 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11368 set_mu_type &= ~0x0a;
11369 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11370 set_mu_type |= 0x02;
11371 set_mu_type &= ~0x08;
11372 }
11373
developera7149722023-01-11 11:36:21 +080011374 new_vendor_patch = check_is_hemu_vendor_new_patch();
11375
11376 if (new_vendor_patch)
11377 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11378 else
11379 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11380
11381 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011382 sprintf(buf, "%u", set_mu_type);
11383 params.value = buf;
11384 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11385 wifi_hostapdWrite(config_file, &params, 1);
11386 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011387 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011388
11389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11390 return RETURN_OK;
11391}
11392
11393INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11394{
11395 struct params params={0};
11396 char config_file[64] = {0};
11397 char buf[64] = {0};
11398 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011399 bool new_vendor_patch = FALSE;
11400 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011401
11402 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11403
developera7149722023-01-11 11:36:21 +080011404 new_vendor_patch = check_is_hemu_vendor_new_patch();
11405
11406 if (new_vendor_patch)
11407 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11408 else
11409 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11410
developer3e6b1692022-09-30 18:04:05 +080011411 if (mu_type == NULL)
11412 return RETURN_ERR;
11413
11414 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011415 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011416
11417 get_mu_type = strtol(buf, NULL, 10);
11418 if (get_mu_type & 0x02)
11419 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11420 else
11421 *mu_type = WIFI_DL_MU_TYPE_NONE;
11422
11423 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11424 return RETURN_OK;
11425}
11426
11427
developer454b9462022-09-13 15:29:16 +080011428INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11429{
11430 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011431 char buf[256] = {0};
11432 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011433 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011434 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011435 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011436 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011437
11438 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11439
developer254882b2022-09-30 17:12:31 +080011440 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011441 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11442 return RETURN_ERR;
11443 }
developer454b9462022-09-13 15:29:16 +080011444
developer254882b2022-09-30 17:12:31 +080011445 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011446 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011447
developer254882b2022-09-30 17:12:31 +080011448 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11449 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011450 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011451 _syscmd(cmd, buf, sizeof(buf));
11452 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11453 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11454 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011455 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011456 _syscmd(cmd, buf, sizeof(buf));
11457 }
11458 if (band == band_5) {
11459 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11460 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011461 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 +080011462 _syscmd(cmd, buf, sizeof(buf));
11463 }
11464 }
11465 }
11466 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011467
developer254882b2022-09-30 17:12:31 +080011468 if (guard_interval == wifi_guard_interval_400)
11469 strcpy(GI, "0.4");
11470 else if (guard_interval == wifi_guard_interval_800)
11471 strcpy(GI, "0.8");
11472 else if (guard_interval == wifi_guard_interval_1600)
11473 strcpy(GI, "1.6");
11474 else if (guard_interval == wifi_guard_interval_3200)
11475 strcpy(GI, "3.2");
11476 else if (guard_interval == wifi_guard_interval_auto)
11477 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011478 // Record GI for get GI function
11479 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11480 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011481 if (f == NULL)
11482 return RETURN_ERR;
11483 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011484 fclose(f);
11485 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11486 return RETURN_OK;
11487}
11488
11489INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11490{
11491 char buf[32] = {0};
11492 char cmd[64] = {0};
11493
11494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11495
11496 if (guard_interval == NULL)
11497 return RETURN_ERR;
11498
developer7c4cd202023-03-01 10:56:29 +080011499 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011500 _syscmd(cmd, buf, sizeof(buf));
11501
11502 if (strncmp(buf, "0.4", 3) == 0)
11503 *guard_interval = wifi_guard_interval_400;
11504 else if (strncmp(buf, "0.8", 3) == 0)
11505 *guard_interval = wifi_guard_interval_800;
11506 else if (strncmp(buf, "1.6", 3) == 0)
11507 *guard_interval = wifi_guard_interval_1600;
11508 else if (strncmp(buf, "3.2", 3) == 0)
11509 *guard_interval = wifi_guard_interval_3200;
11510 else
11511 *guard_interval = wifi_guard_interval_auto;
11512
11513 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11514 return RETURN_OK;
11515}
11516
developer3cc61d12022-09-13 16:36:05 +080011517INT wifi_setBSSColor(INT radio_index, UCHAR color)
11518{
11519 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11520 struct params params = {0};
11521 char config_file[128] = {0};
11522 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011523 UCHAR *color_list;
11524 int color_num = 0;
11525 int maxNumberColors = 64;
11526 BOOL color_is_aval = FALSE;
11527
developerbf0b9dc2023-07-06 14:30:54 +080011528 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011529 return RETURN_ERR;
11530
developer517f3be2023-05-08 10:02:39 +080011531 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11532 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11533 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011534 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011535 }
developer2acb9632023-03-14 14:58:31 +080011536
11537 for (int i = 0; i < color_num; i++) {
11538 if (color_list[i] == color) {
11539 color_is_aval = TRUE;
11540 break;
11541 }
11542 }
11543 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011544 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011545 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11546 return RETURN_ERR;
11547 }
developer3cc61d12022-09-13 16:36:05 +080011548
11549 params.name = "he_bss_color";
11550 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11551 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011552 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011553 wifi_hostapdWrite(config_file, &params, 1);
11554 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011555 wifi_reloadAp(radio_index);
11556
developer517f3be2023-05-08 10:02:39 +080011557 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11559 return RETURN_OK;
11560}
11561
11562INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11563{
developer3cc61d12022-09-13 16:36:05 +080011564 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011565 char cmd[128] = {0};
11566 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011567
developer3cc61d12022-09-13 16:36:05 +080011568 if (NULL == color)
11569 return RETURN_ERR;
11570
developer2acb9632023-03-14 14:58:31 +080011571 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11572 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011573
developer2acb9632023-03-14 14:58:31 +080011574 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11575 _syscmd(cmd, buf, sizeof(buf));
11576 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011577
developer2acb9632023-03-14 14:58:31 +080011578 return RETURN_OK;
11579}
11580
11581INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11582{
11583 char buf[64] = {0};
11584 char cmd[128] = {0};
11585 char interface_name[16] = {0};
11586 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011587
developer2acb9632023-03-14 14:58:31 +080011588 if (NULL == colorList || NULL == numColorReturned)
11589 return RETURN_ERR;
11590
11591 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11592 return RETURN_ERR;
11593
11594 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11595 _syscmd(cmd, buf, sizeof(buf));
11596 color_bitmap = strtoull(buf, NULL, 16);
11597
11598 *numColorReturned = 0;
11599 for (int i = 0; i < maxNumberColors; i++) {
11600 if (color_bitmap & 1) {
11601 colorList[*numColorReturned] = i;
11602 (*numColorReturned) += 1;
11603 }
11604 color_bitmap >>= 1;
11605 }
developer3cc61d12022-09-13 16:36:05 +080011606 return RETURN_OK;
11607}
11608
developer06a01d92022-09-07 16:32:39 +080011609/* multi-psk support */
11610INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11611{
11612 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011613 char interface_name[16] = {0};
11614
developerac6f1142022-12-20 19:26:35 +080011615 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011616 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011617
developerd946fd62022-12-08 18:03:28 +080011618 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11619 interface_name,
developer06a01d92022-09-07 16:32:39 +080011620 mac[0],
11621 mac[1],
11622 mac[2],
11623 mac[3],
11624 mac[4],
11625 mac[5]
11626 );
11627 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11628 _syscmd(cmd, key->wifi_keyId, 64);
11629
11630
11631 return RETURN_OK;
11632}
11633
11634INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11635{
developerd946fd62022-12-08 18:03:28 +080011636 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011637 FILE *fd = NULL;
11638 char fname[100];
11639 char cmd[128] = {0};
11640 char out[64] = {0};
11641 wifi_key_multi_psk_t * key = NULL;
11642 if(keysNumber < 0)
11643 return RETURN_ERR;
11644
developer431128d2022-12-16 15:30:41 +080011645 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011646 fd = fopen(fname, "w");
11647 if (!fd) {
11648 return RETURN_ERR;
11649 }
11650 key= (wifi_key_multi_psk_t *) keys;
11651 for(int i=0; i<keysNumber; ++i, key++) {
11652 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11653 }
11654 fclose(fd);
11655
11656 //reload file
developerac6f1142022-12-20 19:26:35 +080011657 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011658 return RETURN_ERR;
11659 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011660 _syscmd(cmd, out, 64);
11661 return RETURN_OK;
11662}
11663
11664INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11665{
11666 FILE *fd = NULL;
11667 char fname[100];
11668 char * line = NULL;
11669 char * pos = NULL;
11670 size_t len = 0;
11671 ssize_t read = 0;
11672 INT ret = RETURN_OK;
11673 wifi_key_multi_psk_t *keys_it = NULL;
11674
11675 if (keysNumber < 1) {
11676 return RETURN_ERR;
11677 }
11678
developer431128d2022-12-16 15:30:41 +080011679 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011680 fd = fopen(fname, "r");
11681 if (!fd) {
11682 return RETURN_ERR;
11683 }
11684
11685 if (keys == NULL) {
11686 ret = RETURN_ERR;
11687 goto close;
11688 }
11689
11690 keys_it = keys;
11691 while ((read = getline(&line, &len, fd)) != -1) {
11692 //Strip trailing new line if present
11693 if (read > 0 && line[read-1] == '\n') {
11694 line[read-1] = '\0';
11695 }
11696
11697 if(strcmp(line,"keyid=")) {
11698 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11699 if (!(pos = index(line, ' '))) {
11700 ret = RETURN_ERR;
11701 goto close;
11702 }
11703 pos++;
11704 //Here should be 00:00:00:00:00:00
11705 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11706 printf("Not supported MAC: %s\n", pos);
11707 }
11708 if (!(pos = index(pos, ' '))) {
11709 ret = RETURN_ERR;
11710 goto close;
11711 }
11712 pos++;
11713
11714 //The rest is PSK
11715 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11716 keys_it++;
11717
11718 if(--keysNumber <= 0)
11719 break;
11720 }
11721 }
11722
11723close:
11724 free(line);
11725 fclose(fd);
11726 return ret;
11727}
11728/* end of multi-psk support */
11729
11730INT wifi_setNeighborReports(UINT apIndex,
11731 UINT numNeighborReports,
11732 wifi_NeighborReport_t *neighborReports)
11733{
11734 char cmd[256] = { 0 };
11735 char hex_bssid[13] = { 0 };
11736 char bssid[18] = { 0 };
11737 char nr[256] = { 0 };
11738 char ssid[256];
11739 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011740 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011741 INT ret;
11742
11743 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011744 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011745 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011746 return RETURN_ERR;
11747 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 +080011748 system(cmd);
11749
11750 for(unsigned int i = 0; i < numNeighborReports; i++)
11751 {
11752 memset(ssid, 0, sizeof(ssid));
11753 ret = wifi_getSSIDName(apIndex, ssid);
11754 if (ret != RETURN_OK)
11755 return RETURN_ERR;
11756
11757 memset(hex_ssid, 0, sizeof(hex_ssid));
11758 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11759 sprintf(hex_ssid + k,"%02x", ssid[j]);
11760
11761 snprintf(hex_bssid, sizeof(hex_bssid),
11762 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11763 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11764 snprintf(bssid, sizeof(bssid),
11765 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11766 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11767
11768 snprintf(nr, sizeof(nr),
11769 "%s" // bssid
11770 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11771 "%02hhx" // operclass
11772 "%02hhx" // channel
11773 "%02hhx", // phy_mode
11774 hex_bssid,
11775 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11776 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11777 neighborReports[i].opClass,
11778 neighborReports[i].channel,
11779 neighborReports[i].phyTable);
11780
11781 snprintf(cmd, sizeof(cmd),
11782 "hostapd_cli set_neighbor "
11783 "%s " // bssid
11784 "ssid=%s " // ssid
11785 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011786 "-i %s",
11787 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011788
11789 if (WEXITSTATUS(system(cmd)) != 0)
11790 {
11791 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11792 }
11793 }
11794
11795 return RETURN_OK;
11796}
11797
11798INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11799{
11800 return RETURN_OK;
11801}
11802
11803#ifdef _WIFI_HAL_TEST_
11804int main(int argc,char **argv)
11805{
11806 int index;
11807 INT ret=0;
11808 char buf[1024]="";
11809
11810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11811 if(argc<3)
11812 {
11813 if(argc==2)
11814 {
11815 if(!strcmp(argv[1], "init"))
11816 return wifi_init();
11817 if(!strcmp(argv[1], "reset"))
11818 return wifi_reset();
11819 if(!strcmp(argv[1], "wifi_getHalVersion"))
11820 {
11821 char buffer[64];
11822 if(wifi_getHalVersion(buffer)==RETURN_OK)
11823 printf("Version: %s\n", buffer);
11824 else
11825 printf("Error in wifi_getHalVersion\n");
11826 return RETURN_OK;
11827 }
11828 }
11829 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11830 exit(-1);
11831 }
11832
11833 index = atoi(argv[2]);
11834 if(strstr(argv[1], "wifi_getApName")!=NULL)
11835 {
11836 wifi_getApName(index,buf);
11837 printf("Ap name is %s \n",buf);
11838 return 0;
11839 }
11840 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11841 {
11842 BOOL b = FALSE;
11843 BOOL *output_bool = &b;
11844 wifi_getRadioAutoChannelEnable(index,output_bool);
11845 printf("Channel enabled = %d \n",b);
11846 return 0;
11847 }
11848 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11849 {
11850 wifi_getApWpaEncryptionMode(index,buf);
11851 printf("encryption enabled = %s\n",buf);
11852 return 0;
11853 }
11854 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11855 {
11856 BOOL b = FALSE;
11857 BOOL *output_bool = &b;
11858 wifi_getApSsidAdvertisementEnable(index,output_bool);
11859 printf("advertisment enabled = %d\n",b);
11860 return 0;
11861 }
11862 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11863 {
11864 if(argc <= 3 )
11865 {
11866 printf("Insufficient arguments \n");
11867 exit(-1);
11868 }
11869
11870 char sta[20] = {'\0'};
11871 ULLONG handle= 0;
11872 strcpy(sta,argv[3]);
11873 mac_address_t st;
11874 mac_addr_aton(st,sta);
11875
11876 wifi_associated_dev_tid_stats_t tid_stats;
11877 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11878 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11879 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);
11880 }
11881
11882 if(strstr(argv[1], "getApEnable")!=NULL) {
11883 BOOL enable;
11884 ret=wifi_getApEnable(index, &enable);
11885 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11886 }
11887 else if(strstr(argv[1], "setApEnable")!=NULL) {
11888 BOOL enable = atoi(argv[3]);
11889 ret=wifi_setApEnable(index, enable);
11890 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11891 }
11892 else if(strstr(argv[1], "getApStatus")!=NULL) {
11893 char status[64];
11894 ret=wifi_getApStatus(index, status);
11895 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11896 }
11897 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11898 {
11899 wifi_getSSIDNameStatus(index,buf);
11900 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11901 return 0;
11902 }
11903 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11904 wifi_ssidTrafficStats2_t stats={0};
11905 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11906 printf("%s %d: returns %d\n", argv[1], index, ret);
11907 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11908 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11909 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11910 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11911 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11912 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11913 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11914 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11915 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11916 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11917 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11918 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11919 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11920 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11921 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11922 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11923 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11924 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11925 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11926 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11927 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11928 }
11929 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11930 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11931 UINT array_size=0;
11932 UINT i=0;
11933 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11934 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11935 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11936 printf(" neighbor %d:\n", i);
11937 printf(" ap_SSID =%s\n", pt->ap_SSID);
11938 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11939 printf(" ap_Mode =%s\n", pt->ap_Mode);
11940 printf(" ap_Channel =%d\n", pt->ap_Channel);
11941 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11942 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11943 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11944 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11945 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11946 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11947 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11948 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11949 printf(" ap_Noise =%d\n", pt->ap_Noise);
11950 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11951 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11952 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11953 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11954 }
11955 if(neighbor_ap_array)
11956 free(neighbor_ap_array); //make sure to free the list
11957 }
11958 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11959 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11960 UINT array_size=0;
11961 UINT i=0;
11962 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11963 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11964 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11965 printf(" associated_dev %d:\n", i);
11966 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11967 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11968 printf(" cli_SNR =%d\n", pt->cli_SNR);
11969 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11970 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11971 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11972 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11973 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11974 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11975 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11976 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11977 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11978 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11979 }
11980 if(associated_dev_array)
11981 free(associated_dev_array); //make sure to free the list
11982 }
11983
11984 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11985 {
11986#define MAX_ARRAY_SIZE 64
11987 int i, array_size;
11988 char *p, *ch_str;
11989 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11990
11991 if(argc != 5)
11992 {
11993 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11994 exit(-1);
11995 }
11996 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11997
11998 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11999 {
12000 strtok_r(ch_str, ",", &p);
12001 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12002 }
12003 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12004 if(!array_size)
12005 array_size=1;//Need to print current channel statistics
12006 for(i=0; i<array_size; i++)
12007 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12008 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12009 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12010 input_output_channelStats_array[i].ch_number,\
12011 input_output_channelStats_array[i].ch_noise,\
12012 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12013 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12014 input_output_channelStats_array[i].ch_utilization_busy,\
12015 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12016 input_output_channelStats_array[i].ch_utilization_total);
12017 }
12018
12019 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12020 {
12021 if(argc <= 3 )
12022 {
12023 printf("Insufficient arguments \n");
12024 exit(-1);
12025 }
12026 char mac_addr[20] = {'\0'};
12027 wifi_device_t output_struct;
12028 int dev_index = atoi(argv[3]);
12029
12030 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12031 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12032 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);
12033 }
12034
12035 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12036 {
12037 if (argc <= 3)
12038 {
12039 printf("Insufficient arguments\n");
12040 exit(-1);
12041 }
12042 char args[256];
12043 wifi_NeighborReport_t *neighborReports;
12044
12045 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12046 if (!neighborReports)
12047 {
12048 printf("Failed to allocate memory");
12049 exit(-1);
12050 }
12051
12052 for (int i = 3; i < argc; ++i)
12053 {
12054 char *val;
12055 int j = 0;
12056 memset(args, 0, sizeof(args));
12057 strncpy(args, argv[i], sizeof(args));
12058 val = strtok(args, ";");
12059 while (val != NULL)
12060 {
12061 if (j == 0)
12062 {
12063 mac_addr_aton(neighborReports[i - 3].bssid, val);
12064 } else if (j == 1)
12065 {
12066 neighborReports[i - 3].info = strtol(val, NULL, 16);
12067 } else if (j == 2)
12068 {
12069 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12070 } else if (j == 3)
12071 {
12072 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12073 } else if (j == 4)
12074 {
12075 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12076 } else {
12077 printf("Insufficient arguments]n\n");
12078 exit(-1);
12079 }
12080 val = strtok(NULL, ";");
12081 j++;
12082 }
12083 }
12084
12085 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12086 if (ret != RETURN_OK)
12087 {
12088 printf("wifi_setNeighborReports ret = %d", ret);
12089 exit(-1);
12090 }
12091 }
12092 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12093 {
12094 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12095 printf("%s.\n", buf);
12096 else
12097 printf("Error returned\n");
12098 }
12099 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12100 {
12101 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12102 printf("%s.\n", buf);
12103 else
12104 printf("Error returned\n");
12105 }
12106 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12107 {
12108 if (argc <= 2)
12109 {
12110 printf("Insufficient arguments\n");
12111 exit(-1);
12112 }
12113 char buf[64]= {'\0'};
12114 wifi_getRadioOperatingChannelBandwidth(index,buf);
12115 printf("Current bandwidth is %s \n",buf);
12116 return 0;
12117 }
12118 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12119 {
12120 if (argc <= 5)
12121 {
12122 printf("Insufficient arguments\n");
12123 exit(-1);
12124 }
12125 UINT channel = atoi(argv[3]);
12126 UINT width = atoi(argv[4]);
12127 UINT beacon = atoi(argv[5]);
12128 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12129 printf("Result = %d", ret);
12130 }
12131
12132 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12133 return 0;
12134}
12135
12136#endif
12137
12138#ifdef WIFI_HAL_VERSION_3
12139
developer1e5aa162022-09-13 16:06:24 +080012140INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12141{
12142 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12143 if (bitMap & WIFI_BITRATE_1MBPS)
12144 strcat(BasicRate, "1,");
12145 if (bitMap & WIFI_BITRATE_2MBPS)
12146 strcat(BasicRate, "2,");
12147 if (bitMap & WIFI_BITRATE_5_5MBPS)
12148 strcat(BasicRate, "5.5,");
12149 if (bitMap & WIFI_BITRATE_6MBPS)
12150 strcat(BasicRate, "6,");
12151 if (bitMap & WIFI_BITRATE_9MBPS)
12152 strcat(BasicRate, "9,");
12153 if (bitMap & WIFI_BITRATE_11MBPS)
12154 strcat(BasicRate, "11,");
12155 if (bitMap & WIFI_BITRATE_12MBPS)
12156 strcat(BasicRate, "12,");
12157 if (bitMap & WIFI_BITRATE_18MBPS)
12158 strcat(BasicRate, "18,");
12159 if (bitMap & WIFI_BITRATE_24MBPS)
12160 strcat(BasicRate, "24,");
12161 if (bitMap & WIFI_BITRATE_36MBPS)
12162 strcat(BasicRate, "36,");
12163 if (bitMap & WIFI_BITRATE_48MBPS)
12164 strcat(BasicRate, "48,");
12165 if (bitMap & WIFI_BITRATE_54MBPS)
12166 strcat(BasicRate, "54,");
12167 if (strlen(BasicRate) != 0) // remove last comma
12168 BasicRate[strlen(BasicRate) - 1] = '\0';
12169 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12170 return RETURN_OK;
12171}
12172
12173INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12174{
12175 UINT BitMap = 0;
12176 char *rate;
12177
12178 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12179 rate = strtok(BasicRatesList, ",");
12180 while(rate != NULL)
12181 {
12182 if (strcmp(rate, "1") == 0)
12183 BitMap |= WIFI_BITRATE_1MBPS;
12184 else if (strcmp(rate, "2") == 0)
12185 BitMap |= WIFI_BITRATE_2MBPS;
12186 else if (strcmp(rate, "5.5") == 0)
12187 BitMap |= WIFI_BITRATE_5_5MBPS;
12188 else if (strcmp(rate, "6") == 0)
12189 BitMap |= WIFI_BITRATE_6MBPS;
12190 else if (strcmp(rate, "9") == 0)
12191 BitMap |= WIFI_BITRATE_9MBPS;
12192 else if (strcmp(rate, "11") == 0)
12193 BitMap |= WIFI_BITRATE_11MBPS;
12194 else if (strcmp(rate, "12") == 0)
12195 BitMap |= WIFI_BITRATE_12MBPS;
12196 else if (strcmp(rate, "18") == 0)
12197 BitMap |= WIFI_BITRATE_18MBPS;
12198 else if (strcmp(rate, "24") == 0)
12199 BitMap |= WIFI_BITRATE_24MBPS;
12200 else if (strcmp(rate, "36") == 0)
12201 BitMap |= WIFI_BITRATE_36MBPS;
12202 else if (strcmp(rate, "48") == 0)
12203 BitMap |= WIFI_BITRATE_48MBPS;
12204 else if (strcmp(rate, "54") == 0)
12205 BitMap |= WIFI_BITRATE_54MBPS;
12206 rate = strtok(NULL, ",");
12207 }
12208 *basicRateBitMap = BitMap;
12209 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12210 return RETURN_OK;
12211}
12212
developer7c4cd202023-03-01 10:56:29 +080012213INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12214{
12215 int center_channel = 0;
12216 char central_channel_str[16] = {0};
12217 char config_file[32] = {0};
12218 struct params param = {0};
12219
12220 center_channel = util_unii_6g_centerfreq("HT320", channel);
12221 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12222 if (channel >= 193)
12223 return RETURN_ERR;
12224 if (channel >= 33) {
12225 if (channel > center_channel)
12226 center_channel += 32;
12227 else
12228 center_channel -= 32;
12229 }
12230 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12231 if (channel <= 29)
12232 return RETURN_ERR;
12233 }
12234 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12235 param.name = "eht_oper_centr_freq_seg0_idx";
12236 param.value = central_channel_str;
12237 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12238 wifi_hostapdWrite(config_file, &param, 1);
12239
12240 return RETURN_OK;
12241}
12242
12243INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12244{
12245 int op_class = 0;
12246 char config_file[32] = {0};
12247 char op_class_str[8] = {0};
12248 struct params param = {0};
12249
12250 if (bandwidth == 20)
12251 op_class = 131;
12252 else if (bandwidth == 40)
12253 op_class = 132;
12254 else if (bandwidth == 80)
12255 op_class = 133;
12256 else if (bandwidth == 160)
12257 op_class = 134;
12258 else if (bandwidth == 320)
12259 op_class = 137;
12260 else
12261 return RETURN_ERR;
12262 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12263 param.name = "op_class";
12264 param.value = op_class_str;
12265 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12266 wifi_hostapdWrite(config_file, &param, 1);
12267 return RETURN_OK;
12268}
12269
12270INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12271{
12272 char config_file[32] = {0};
12273 char buf [16] = {0};
12274
12275 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12276 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12277 return RETURN_ERR; // 6g band should set op_class
12278 *class = (UINT)strtoul(buf, NULL, 10);
12279
12280 return RETURN_OK;
12281}
12282
developer1e5aa162022-09-13 16:06:24 +080012283// 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 +080012284INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12285{
developer1e5aa162022-09-13 16:06:24 +080012286 char buf[128] = {0};
12287 char cmd[128] = {0};
12288 char config_file[64] = {0};
12289 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012290 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012291 wifi_radio_operationParam_t current_param;
12292
12293 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12294
12295 multiple_set = TRUE;
12296 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12297 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12298 return RETURN_ERR;
12299 }
12300 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12301 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12302 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12303 return RETURN_ERR;
12304 }
12305 }
developer5884e982022-10-06 10:52:50 +080012306
12307 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12308 bandwidth = 20;
12309 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12310 bandwidth = 40;
12311 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12312 bandwidth = 80;
12313 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12314 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012315 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12316 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012317 if (operationParam->autoChannelEnabled){
12318 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12319 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12320 return RETURN_ERR;
12321 }
12322 }else{
developer1e5aa162022-09-13 16:06:24 +080012323 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12324 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12325 return RETURN_ERR;
12326 }
12327 }
developer5884e982022-10-06 10:52:50 +080012328
developer7c4cd202023-03-01 10:56:29 +080012329 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12330 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12331 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12332 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12333 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12334 return RETURN_ERR;
12335 }
12336 }
12337
12338 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12339 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12340 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12341 return RETURN_ERR;
12342 }
12343 }
12344
developer1e5aa162022-09-13 16:06:24 +080012345 if (current_param.variant != operationParam->variant) {
12346 // Two different definition bit map, so need to check every bit.
12347 if (operationParam->variant & WIFI_80211_VARIANT_A)
12348 set_mode |= WIFI_MODE_A;
12349 if (operationParam->variant & WIFI_80211_VARIANT_B)
12350 set_mode |= WIFI_MODE_B;
12351 if (operationParam->variant & WIFI_80211_VARIANT_G)
12352 set_mode |= WIFI_MODE_G;
12353 if (operationParam->variant & WIFI_80211_VARIANT_N)
12354 set_mode |= WIFI_MODE_N;
12355 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12356 set_mode |= WIFI_MODE_AC;
12357 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12358 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012359 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12360 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012361 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12362 memset(buf, 0, sizeof(buf));
12363 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12364 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12365 return RETURN_ERR;
12366 }
12367 }
12368 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12369 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12370 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12371 return RETURN_ERR;
12372 }
12373 }
12374 if (current_param.beaconInterval != operationParam->beaconInterval) {
12375 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12376 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12377 return RETURN_ERR;
12378 }
12379 }
12380 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12381 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12382 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12383 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12384 return RETURN_ERR;
12385 }
12386 }
12387 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12388 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12389 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12390 return RETURN_ERR;
12391 }
12392 }
12393 if (current_param.guardInterval != operationParam->guardInterval) {
12394 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12395 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12396 return RETURN_ERR;
12397 }
12398 }
12399 if (current_param.transmitPower != operationParam->transmitPower) {
12400 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12401 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12402 return RETURN_ERR;
12403 }
12404 }
12405 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12406 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12407 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12408 return RETURN_ERR;
12409 }
12410 }
12411 if (current_param.obssCoex != operationParam->obssCoex) {
12412 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12413 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12414 return RETURN_ERR;
12415 }
12416 }
12417 if (current_param.stbcEnable != operationParam->stbcEnable) {
12418 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12419 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12420 return RETURN_ERR;
12421 }
12422 }
developer5735d092023-09-19 20:12:26 +080012423 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12424 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12425 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12426 return RETURN_ERR;
12427 }
12428 }
developer1e5aa162022-09-13 16:06:24 +080012429
12430 // if enable is true, then restart the radio
12431 wifi_setRadioEnable(index, FALSE);
12432 if (operationParam->enable == TRUE)
12433 wifi_setRadioEnable(index, TRUE);
12434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12435
developer06a01d92022-09-07 16:32:39 +080012436 return RETURN_OK;
12437}
12438
12439INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12440{
developer1e5aa162022-09-13 16:06:24 +080012441 char band[64] = {0};
12442 char buf[256] = {0};
12443 char config_file[64] = {0};
12444 char cmd[128] = {0};
12445 int ret = RETURN_ERR;
12446 int mode = 0;
12447 ULONG channel = 0;
12448 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012449
12450 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12451 printf("Entering %s index = %d\n", __func__, (int)index);
12452
developer1e5aa162022-09-13 16:06:24 +080012453 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12454 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12455 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012456 {
developer1e5aa162022-09-13 16:06:24 +080012457 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012458 return RETURN_ERR;
12459 }
12460 operationParam->enable = enabled;
12461
12462 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012463 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012464 {
developer1e5aa162022-09-13 16:06:24 +080012465 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012466 return RETURN_ERR;
12467 }
12468
12469 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012470 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012471 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012472 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012473 else if (!strcmp(band, "6GHz"))
12474 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012475 else
12476 {
developer1e5aa162022-09-13 16:06:24 +080012477 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012478 band);
12479 }
12480
developer1e5aa162022-09-13 16:06:24 +080012481 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12482 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12483 operationParam->channel = 0;
12484 operationParam->autoChannelEnabled = TRUE;
12485 } else {
12486 operationParam->channel = strtol(buf, NULL, 10);
12487 operationParam->autoChannelEnabled = FALSE;
12488 }
12489
developer06a01d92022-09-07 16:32:39 +080012490 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012491 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12492 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12493 return RETURN_ERR;
12494 }
developer06a01d92022-09-07 16:32:39 +080012495 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12496 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12497 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012498 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012499 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12500 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012501 else
12502 {
developer1e5aa162022-09-13 16:06:24 +080012503 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12504 return false;
developer06a01d92022-09-07 16:32:39 +080012505 }
12506
developer7c4cd202023-03-01 10:56:29 +080012507 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12508 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12509 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12510 return RETURN_ERR;
12511 }
12512 }
12513
developer1e5aa162022-09-13 16:06:24 +080012514 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12515 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12516 return RETURN_ERR;
12517 }
12518 // Two different definition bit map, so need to check every bit.
12519 if (mode & WIFI_MODE_A)
12520 operationParam->variant |= WIFI_80211_VARIANT_A;
12521 if (mode & WIFI_MODE_B)
12522 operationParam->variant |= WIFI_80211_VARIANT_B;
12523 if (mode & WIFI_MODE_G)
12524 operationParam->variant |= WIFI_80211_VARIANT_G;
12525 if (mode & WIFI_MODE_N)
12526 operationParam->variant |= WIFI_80211_VARIANT_N;
12527 if (mode & WIFI_MODE_AC)
12528 operationParam->variant |= WIFI_80211_VARIANT_AC;
12529 if (mode & WIFI_MODE_AX)
12530 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012531 if (mode & WIFI_MODE_BE)
12532 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012533 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12534 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12535 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012536 }
developer1e5aa162022-09-13 16:06:24 +080012537 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12538 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12539 return RETURN_ERR;
12540 }
12541 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12542 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12543 return RETURN_ERR;
12544 }
developer06a01d92022-09-07 16:32:39 +080012545
developer1e5aa162022-09-13 16:06:24 +080012546 memset(buf, 0, sizeof(buf));
12547 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12548 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12549 return RETURN_ERR;
12550 }
12551 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12552
12553 memset(buf, 0, sizeof(buf));
12554 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12555 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12556 return RETURN_ERR;
12557 }
12558 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12559
12560 memset(buf, 0, sizeof(buf));
12561 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12562 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12563
12564 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12565 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12566 return RETURN_ERR;
12567 }
12568 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12569 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12570 return RETURN_ERR;
12571 }
12572
12573 memset(buf, 0, sizeof(buf));
12574 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12575 if (strcmp(buf, "-1") == 0) {
12576 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12577 operationParam->ctsProtection = FALSE;
12578 } else {
12579 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12580 operationParam->ctsProtection = TRUE;
12581 }
12582
12583 memset(buf, 0, sizeof(buf));
12584 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12585 if (strcmp(buf, "0") == 0)
12586 operationParam->obssCoex = FALSE;
12587 else
12588 operationParam->obssCoex = TRUE;
12589
12590 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12591 _syscmd(cmd, buf, sizeof(buf));
12592 if (strlen(buf) != 0)
12593 operationParam->stbcEnable = TRUE;
12594 else
12595 operationParam->stbcEnable = FALSE;
12596
developer5735d092023-09-19 20:12:26 +080012597 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12598 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12599 return RETURN_ERR;
12600 }
developer1e5aa162022-09-13 16:06:24 +080012601
12602 // Below value is hardcoded
12603
12604 operationParam->numSecondaryChannels = 0;
12605 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12606 operationParam->channelSecondary[i] = 0;
12607 }
12608 operationParam->csa_beacon_count = 15;
12609 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012610
12611 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12612 return RETURN_OK;
12613}
12614
12615static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12616{
developerc086fb72022-10-04 10:18:22 +080012617 int max_radio_num = 0;
12618
12619 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012620 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012621 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12622 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012623 }
12624
developerc086fb72022-10-04 10:18:22 +080012625 return (arrayIndex * max_radio_num) + radioIndex;
12626}
developer06a01d92022-09-07 16:32:39 +080012627
developerc086fb72022-10-04 10:18:22 +080012628wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12629 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12630 return WIFI_BITRATE_1MBPS;
12631 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12632 return WIFI_BITRATE_2MBPS;
12633 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12634 return WIFI_BITRATE_5_5MBPS;
12635 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12636 return WIFI_BITRATE_6MBPS;
12637 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12638 return WIFI_BITRATE_9MBPS;
12639 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12640 return WIFI_BITRATE_11MBPS;
12641 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12642 return WIFI_BITRATE_12MBPS;
12643 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12644 return WIFI_BITRATE_18MBPS;
12645 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12646 return WIFI_BITRATE_24MBPS;
12647 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12648 return WIFI_BITRATE_36MBPS;
12649 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12650 return WIFI_BITRATE_48MBPS;
12651 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12652 return WIFI_BITRATE_54MBPS;
12653 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012654}
12655
developer1d57d002022-10-12 18:03:15 +080012656INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12657{
12658 if (beacon == WIFI_BITRATE_1MBPS)
12659 strcpy(beacon_str, "1Mbps");
12660 else if (beacon == WIFI_BITRATE_2MBPS)
12661 strcpy(beacon_str, "2Mbps");
12662 else if (beacon == WIFI_BITRATE_5_5MBPS)
12663 strcpy(beacon_str, "5.5Mbps");
12664 else if (beacon == WIFI_BITRATE_6MBPS)
12665 strcpy(beacon_str, "6Mbps");
12666 else if (beacon == WIFI_BITRATE_9MBPS)
12667 strcpy(beacon_str, "9Mbps");
12668 else if (beacon == WIFI_BITRATE_11MBPS)
12669 strcpy(beacon_str, "11Mbps");
12670 else if (beacon == WIFI_BITRATE_12MBPS)
12671 strcpy(beacon_str, "12Mbps");
12672 else if (beacon == WIFI_BITRATE_18MBPS)
12673 strcpy(beacon_str, "18Mbps");
12674 else if (beacon == WIFI_BITRATE_24MBPS)
12675 strcpy(beacon_str, "24Mbps");
12676 else if (beacon == WIFI_BITRATE_36MBPS)
12677 strcpy(beacon_str, "36Mbps");
12678 else if (beacon == WIFI_BITRATE_48MBPS)
12679 strcpy(beacon_str, "48Mbps");
12680 else if (beacon == WIFI_BITRATE_54MBPS)
12681 strcpy(beacon_str, "54Mbps");
12682 return RETURN_OK;
12683}
12684
developer74ed4192023-09-21 17:15:17 +080012685void checkVapStatus(int apIndex, bool *enable)
12686{
12687 char if_name[16] = {0};
12688 char cmd[128] = {0};
12689 char buf[128] = {0};
12690
12691 *enable = FALSE;
12692 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12693 return;
12694
12695 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12696 _syscmd(cmd, buf, sizeof(buf));
12697 if (strlen(buf) > 0)
12698 *enable = TRUE;
12699 return;
12700}
12701
developer06a01d92022-09-07 16:32:39 +080012702INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12703{
developerc086fb72022-10-04 10:18:22 +080012704 INT mode = 0;
12705 INT ret = -1;
12706 INT output = 0;
12707 int i = 0;
12708 int vap_index = 0;
12709 BOOL enabled = FALSE;
12710 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012711 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012712
developer06a01d92022-09-07 16:32:39 +080012713
12714 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12715 printf("Entering %s index = %d\n", __func__, (int)index);
12716
developera77d84b2023-02-22 16:10:50 +080012717 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012718 {
developerc086fb72022-10-04 10:18:22 +080012719 map->vap_array[i].radio_index = index;
12720
developer06a01d92022-09-07 16:32:39 +080012721 vap_index = array_index_to_vap_index(index, i);
12722 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012723 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012724
developerc086fb72022-10-04 10:18:22 +080012725 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012726
12727 map->vap_array[i].vap_index = vap_index;
12728
12729 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012730 ret = wifi_getApName(vap_index, buf);
12731 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012732 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12733
developerc086fb72022-10-04 10:18:22 +080012734 return RETURN_ERR;
12735 }
12736 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12737
12738 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012739 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012740 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012741 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012742 return RETURN_ERR;
12743 }
12744 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 +080012745
developer74ed4192023-09-21 17:15:17 +080012746 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012747 map->vap_array[i].u.bss_info.enabled = enabled;
12748
developerc086fb72022-10-04 10:18:22 +080012749 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12750 if (ret != RETURN_OK) {
12751 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12752 return RETURN_ERR;
12753 }
developer06a01d92022-09-07 16:32:39 +080012754 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012755
12756 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12757 if (ret != RETURN_OK) {
12758 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12759 return RETURN_ERR;
12760 }
12761 map->vap_array[i].u.bss_info.isolation = enabled;
12762
12763 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12764 if (ret != RETURN_OK) {
12765 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12766 return RETURN_ERR;
12767 }
12768 map->vap_array[i].u.bss_info.bssMaxSta = output;
12769
12770 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12771 if (ret != RETURN_OK) {
12772 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12773 return RETURN_ERR;
12774 }
12775 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012776
developerc086fb72022-10-04 10:18:22 +080012777 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12778 if (ret != RETURN_OK) {
12779 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12780 return RETURN_ERR;
12781 }
12782 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012783
developerc086fb72022-10-04 10:18:22 +080012784 ret = wifi_getApSecurity(vap_index, &security);
12785 if (ret != RETURN_OK) {
12786 printf("%s: wifi_getApSecurity return error\n", __func__);
12787 return RETURN_ERR;
12788 }
12789 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012790
developerc086fb72022-10-04 10:18:22 +080012791 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12792 if (ret != RETURN_OK) {
12793 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12794 return RETURN_ERR;
12795 }
12796 if (mode == 0)
12797 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12798 else
12799 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12800 if (mode == 1)
12801 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12802 else if (mode == 2)
12803 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012804
developerc086fb72022-10-04 10:18:22 +080012805 ret = wifi_getApWmmEnable(vap_index, &enabled);
12806 if (ret != RETURN_OK) {
12807 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12808 return RETURN_ERR;
12809 }
12810 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012811
developerc086fb72022-10-04 10:18:22 +080012812 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12813 if (ret != RETURN_OK) {
12814 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012815 return RETURN_ERR;
12816 }
developerc086fb72022-10-04 10:18:22 +080012817 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012818
12819 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012820 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012821 if (ret != RETURN_OK) {
12822 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12823 return RETURN_ERR;
12824 }
12825 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012826
developerc086fb72022-10-04 10:18:22 +080012827 memset(buf, 0, sizeof(buf));
12828 ret = wifi_getBaseBSSID(vap_index, buf);
12829 if (ret != RETURN_OK) {
12830 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12831 return RETURN_ERR;
12832 }
12833 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12834 &map->vap_array[i].u.bss_info.bssid[0],
12835 &map->vap_array[i].u.bss_info.bssid[1],
12836 &map->vap_array[i].u.bss_info.bssid[2],
12837 &map->vap_array[i].u.bss_info.bssid[3],
12838 &map->vap_array[i].u.bss_info.bssid[4],
12839 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012840 // 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]);
12841
12842 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12843 if (ret != RETURN_OK) {
12844 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12845 return RETURN_ERR;
12846 }
12847 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080012848
12849 ret = wifi_getApWpsEnable(vap_index, &enabled);
12850 if (ret != RETURN_OK) {
12851 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
12852 return RETURN_ERR;
12853 }
12854
12855 map->vap_array[i].u.bss_info.wps.enable = enabled;
12856
developera77d84b2023-02-22 16:10:50 +080012857 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080012858 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012859 }
12860 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12861 return RETURN_OK;
12862}
12863
developer431128d2022-12-16 15:30:41 +080012864
developerd946fd62022-12-08 18:03:28 +080012865static int prepareInterface(UINT apIndex, char *new_interface)
12866{
12867 char cur_interface[16] = {0};
12868 char config_file[128] = {0};
12869 char cmd[128] = {0};
12870 char buf[16] = {0};
12871 int max_radio_num = 0;
12872 int radioIndex = -1;
12873 int phyIndex = -1;
12874
12875 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12876 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12877
12878 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12879 wifi_getMaxRadioNumber(&max_radio_num);
12880 radioIndex = apIndex % max_radio_num;
12881 phyIndex = radio_index_to_phy(radioIndex);
12882 // disable and del old interface, then add new interface
12883 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080012884 if (!(apIndex/max_radio_num)) {
12885 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
12886 _syscmd(cmd, buf, sizeof(buf));
12887 }
developerd946fd62022-12-08 18:03:28 +080012888 }
developer431128d2022-12-16 15:30:41 +080012889 // update the vap status file
12890 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12891 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012892 return RETURN_OK;
12893}
12894
developer06a01d92022-09-07 16:32:39 +080012895INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12896{
developerd946fd62022-12-08 18:03:28 +080012897 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012898 unsigned int i;
12899 wifi_vap_info_t *vap_info = NULL;
12900 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012901 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012902 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012903 char buf[256] = {0};
12904 char cmd[128] = {0};
12905 char config_file[64] = {0};
12906 char bssid[32] = {0};
12907 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012908 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012909
12910 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12911 printf("Entering %s index = %d\n", __func__, (int)index);
12912 for (i = 0; i < map->num_vaps; i++)
12913 {
developer1d57d002022-10-12 18:03:15 +080012914 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012915 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012916
12917 // Check vap status file to enable multiple ap if the system boot.
12918 checkVapStatus(vap_info->vap_index, &enable);
12919 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012920 continue;
developer06a01d92022-09-07 16:32:39 +080012921
developer1d57d002022-10-12 18:03:15 +080012922 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12923
developer431128d2022-12-16 15:30:41 +080012924 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12925 enable = FALSE;
12926
12927 // multi-ap first up need to copy current radio config
12928 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012929 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12930 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012931 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12932 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12933 } else {
12934 // Check whether the interface name is valid or this ap change it.
12935 int apIndex = -1;
12936 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12937 if (apIndex != -1 && apIndex != vap_info->vap_index)
12938 continue;
12939 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012940 }
developer06a01d92022-09-07 16:32:39 +080012941
developer1d57d002022-10-12 18:03:15 +080012942 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012943 params[0].name = "interface";
12944 params[0].value = vap_info->vap_name;
12945 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12946 params[1].name = "bssid";
12947 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012948 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012949 params[2].name = "wpa_psk_file";
12950 params[2].value = psk_file;
12951
12952 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12953 wifi_hostapdWrite(config_file, params, 3);
12954
12955 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12956 _syscmd(cmd, buf, sizeof(buf));
12957
12958 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12959 if (ret != RETURN_OK) {
12960 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12961 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012962 }
developer1d57d002022-10-12 18:03:15 +080012963
12964 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12965 if (ret != RETURN_OK) {
12966 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12967 return RETURN_ERR;
12968 }
12969
12970 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12971 if (ret != RETURN_OK) {
12972 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12973 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012974 }
12975
developer1d57d002022-10-12 18:03:15 +080012976 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12977 if (ret != RETURN_OK) {
12978 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12979 return RETURN_ERR;
12980 }
developer06a01d92022-09-07 16:32:39 +080012981
developer1d57d002022-10-12 18:03:15 +080012982 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12983 if (ret != RETURN_OK) {
12984 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12985 return RETURN_ERR;
12986 }
developer06a01d92022-09-07 16:32:39 +080012987
developer1d57d002022-10-12 18:03:15 +080012988 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12989 if (ret != RETURN_OK) {
12990 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12991 return RETURN_ERR;
12992 }
12993
developer804c64f2022-10-19 13:54:40 +080012994 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012995 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012996 }else {
12997 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012998 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012999 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13000 _syscmd(cmd, buf, sizeof(buf));
13001 }else{
developer1d57d002022-10-12 18:03:15 +080013002 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080013003 }
developer1d57d002022-10-12 18:03:15 +080013004 }
13005
13006 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13007 if (ret != RETURN_OK) {
13008 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13009 return RETURN_ERR;
13010 }
13011
13012 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13013 if (ret != RETURN_OK) {
13014 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13015 return RETURN_ERR;
13016 }
13017
13018 memset(buf, 0, sizeof(buf));
13019 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13020 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
13021 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13022 if (ret != RETURN_OK) {
13023 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13024 return RETURN_ERR;
13025 }
13026
developer1d57d002022-10-12 18:03:15 +080013027 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13028 if (ret != RETURN_OK) {
13029 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13030 return RETURN_ERR;
13031 }
13032
13033 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13034 if (ret != RETURN_OK) {
13035 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13036 return RETURN_ERR;
13037 }
developer06a01d92022-09-07 16:32:39 +080013038
developer894affa2023-05-10 18:13:19 +080013039 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
13040 if (ret != RETURN_OK) {
13041 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
13042 return RETURN_ERR;
13043 }
13044
developer2f995fb2023-02-24 10:40:44 +080013045 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080013046 if (vap_info->u.bss_info.enabled == TRUE)
13047 wifi_setApEnable(vap_info->vap_index, TRUE);
13048
developer2f995fb2023-02-24 10:40:44 +080013049 multiple_set = FALSE;
13050
13051 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080013052 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080013053 // The set wps methods function should check whether wps is configured.
13054 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
13055 if (ret != RETURN_OK) {
13056 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
13057 return RETURN_ERR;
13058 }
13059 // wifi_setApWpsConfigMethodsEnabled only write to config.
13060 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13061 if (ret != RETURN_OK) {
13062 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13063 return RETURN_ERR;
13064 }
13065 }
developer2f995fb2023-02-24 10:40:44 +080013066
developer894affa2023-05-10 18:13:19 +080013067 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013068 }
developerfb09ba62023-06-09 17:03:21 +080013069
13070 // IGMP Snooping enable should be placed after all hostapd_reload.
13071 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13072 if (ret != RETURN_OK) {
13073 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13074 return RETURN_ERR;
13075 }
13076
developer06a01d92022-09-07 16:32:39 +080013077 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13078 return RETURN_OK;
13079}
13080
13081int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13082{
13083 char *token, *next;
13084 const char s[2] = ",";
13085 int count =0;
13086
13087 /* get the first token */
13088 token = strtok_r(pchannels, s, &next);
13089
13090 /* walk through other tokens */
13091 while( token != NULL && count < MAX_CHANNELS) {
13092 chlistptr->channels_list[count++] = atoi(token);
13093 token = strtok_r(NULL, s, &next);
13094 }
13095
13096 return count;
13097}
13098
13099static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13100{
13101 INT status;
13102 wifi_channels_list_t *chlistp;
13103 CHAR output_string[64];
13104 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013105 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013106 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013107
13108 if(rcap == NULL)
13109 {
13110 return RETURN_ERR;
13111 }
13112
13113 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013114 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013115
developer1e5aa162022-09-13 16:06:24 +080013116 if (band == band_2_4)
13117 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13118 else if (band == band_5)
13119 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13120 else if (band == band_6)
13121 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013122
13123 chlistp = &(rcap->channel_list[0]);
13124 memset(pchannels, 0, sizeof(pchannels));
13125
13126 /* possible number of radio channels */
13127 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13128 {
13129 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13130 }
13131 /* Number of channels and list*/
13132 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13133
13134 /* autoChannelSupported */
13135 /* always ON with wifi_getRadioAutoChannelSupported */
13136 rcap->autoChannelSupported = TRUE;
13137
13138 /* DCSSupported */
13139 /* always ON with wifi_getRadioDCSSupported */
13140 rcap->DCSSupported = TRUE;
13141
13142 /* zeroDFSSupported - TBD */
13143 rcap->zeroDFSSupported = FALSE;
13144
13145 /* Supported Country List*/
13146 memset(output_string, 0, sizeof(output_string));
13147 status = wifi_getRadioCountryCode(radioIndex, output_string);
13148 if( status != 0 ) {
13149 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13150 return RETURN_ERR;
13151 } else {
13152 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13153 }
13154 if(!strcmp(output_string,"US")){
13155 rcap->countrySupported[0] = wifi_countrycode_US;
13156 rcap->countrySupported[1] = wifi_countrycode_CA;
13157 } else if (!strcmp(output_string,"CA")) {
13158 rcap->countrySupported[0] = wifi_countrycode_CA;
13159 rcap->countrySupported[1] = wifi_countrycode_US;
13160 } else {
13161 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13162 }
13163
13164 rcap->numcountrySupported = 2;
13165
13166 /* csi */
13167 rcap->csi.maxDevices = 8;
13168 rcap->csi.soudingFrameSupported = TRUE;
13169
developer7930d352022-12-21 17:55:42 +080013170 wifi_GetInterfaceName(radioIndex, interface_name);
13171 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013172
13173 /* channelWidth - all supported bandwidths */
13174 int i=0;
13175 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013176
13177 /* mode - all supported variants */
13178 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13179 wifi_getRadioSupportedStandards(radioIndex, output_string);
13180
developer06a01d92022-09-07 16:32:39 +080013181 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13182 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13183 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013184 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013185
developer7c4cd202023-03-01 10:56:29 +080013186 if (strstr(output_string, "n") != NULL)
13187 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13188 if (strstr(output_string, "ax") != NULL)
13189 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13190 if (strstr(output_string, "be") != NULL)
13191 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13192 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013193 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13194 WIFI_CHANNELBANDWIDTH_40MHZ |
13195 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013196 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013197
developer7c4cd202023-03-01 10:56:29 +080013198 if (strstr(output_string, "n") != NULL)
13199 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13200 if (strstr(output_string, "ac") != NULL)
13201 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13202 if (strstr(output_string, "ax") != NULL)
13203 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13204 if (strstr(output_string, "be") != NULL)
13205 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13206 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13207 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13208 WIFI_CHANNELBANDWIDTH_40MHZ |
13209 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013210 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013211
13212 if (strstr(output_string, "be") != NULL) {
13213 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13214 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13215 }
developer06a01d92022-09-07 16:32:39 +080013216 }
developer7c4cd202023-03-01 10:56:29 +080013217
developer06a01d92022-09-07 16:32:39 +080013218 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13219 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13220
13221 /* supportedBitRate - all supported bitrates */
13222 rcap->supportedBitRate[i] = 0;
13223 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13224 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13225 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13226 }
developer1e5aa162022-09-13 16:06:24 +080013227 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013228 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13229 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13230 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13231 }
13232
13233
13234 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13235 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13236 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13237 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13238 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13239 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13240 rcap->cipherSupported = 0;
13241 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13242 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13243
13244 return RETURN_OK;
13245}
13246
13247INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13248{
developer30423732022-12-01 16:17:49 +080013249 INT status = 0, radioIndex = 0;
13250 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013251 int iter = 0;
developer30423732022-12-01 16:17:49 +080013252 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013253 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013254 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013255
13256 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13257
13258 memset(cap, 0, sizeof(wifi_hal_capability_t));
13259
13260 /* version */
13261 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13262 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13263
13264 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013265 wifi_getMaxRadioNumber(&max_num_radios);
13266 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013267
13268 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13269 {
13270 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13271 if (status != 0) {
13272 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13273 return RETURN_ERR;
13274 }
13275
13276 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13277 {
developer804c64f2022-10-19 13:54:40 +080013278 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013279 {
13280 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13281 return RETURN_ERR;
13282 }
13283 iface_info = &cap->wifi_prop.interface_map[iter];
13284 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13285 iface_info->rdk_radio_index = radioIndex;
13286 memset(output, 0, sizeof(output));
13287 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13288 {
13289 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13290 }
13291 // TODO: bridge name
13292 // TODO: vlan id
13293 // TODO: primary
13294 iface_info->index = array_index_to_vap_index(radioIndex, j);
13295 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013296 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013297 {
13298 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13299 }
13300 iter++;
13301 }
13302 }
13303
13304 cap->BandSteeringSupported = FALSE;
13305 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13306 return RETURN_OK;
13307}
13308
developer9df4e652022-10-11 11:27:38 +080013309INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13310{
13311 struct params h_config={0};
13312 char config_file[64] = {0};
13313
13314 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13315
13316 h_config.name = "okc";
13317 h_config.value = okc_enable?"1":"0";
13318
13319 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13320 wifi_hostapdWrite(config_file, &h_config, 1);
13321 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13322
13323 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13324 return RETURN_OK;
13325}
13326
13327INT wifi_setSAEMFP(int ap_index, BOOL enable)
13328{
13329 struct params h_config={0};
13330 char config_file[64] = {0};
13331 char buf[128] = {0};
13332
13333 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13334
13335 h_config.name = "sae_require_mfp";
13336 h_config.value = enable?"1":"0";
13337
13338 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13339 wifi_hostapdWrite(config_file, &h_config, 1);
13340 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13341
13342 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13343 return RETURN_OK;
13344}
13345
13346INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13347{
13348 struct params h_config={0};
13349 char config_file[64] = {0};
13350 char buf[128] = {0};
13351
13352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13353
13354 h_config.name = "sae_pwe";
13355 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13356 h_config.value = buf;
13357
13358 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13359 wifi_hostapdWrite(config_file, &h_config, 1);
13360 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13361
13362 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13363 return RETURN_OK;
13364}
13365
13366INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13367{
13368 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13369 struct params h_config={0};
13370 char config_file[64] = {0};
13371
13372 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13373
13374 h_config.name = "wpa_disable_eapol_key_retries";
13375 h_config.value = disable_EAPOL_retries?"1":"0";
13376
13377 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13378 wifi_hostapdWrite(config_file, &h_config, 1);
13379 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13380
13381 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13382 return RETURN_OK;
13383}
13384
developer06a01d92022-09-07 16:32:39 +080013385INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13386{
developer587c1b62022-09-27 15:58:59 +080013387 char buf[128] = {0};
13388 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013389 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013390 char password[64] = {0};
13391 char mfp[32] = {0};
13392 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013393 BOOL okc_enable = FALSE;
13394 BOOL sae_MFP = FALSE;
13395 BOOL disable_EAPOL_retries = TRUE;
13396 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013397 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013398 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013399
13400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13401
13402 multiple_set = TRUE;
13403 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13404 if (security->mode == wifi_security_mode_none) {
13405 strcpy(wpa_mode, "None");
13406 } else if (security->mode == wifi_security_mode_wpa_personal)
13407 strcpy(wpa_mode, "WPA-Personal");
13408 else if (security->mode == wifi_security_mode_wpa2_personal)
13409 strcpy(wpa_mode, "WPA2-Personal");
13410 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13411 strcpy(wpa_mode, "WPA-WPA2-Personal");
13412 else if (security->mode == wifi_security_mode_wpa_enterprise)
13413 strcpy(wpa_mode, "WPA-Enterprise");
13414 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13415 strcpy(wpa_mode, "WPA2-Enterprise");
13416 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13417 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013418 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013419 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013420 okc_enable = TRUE;
13421 sae_MFP = TRUE;
13422 sae_pwe = 2;
13423 disable_EAPOL_retries = FALSE;
13424 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013425 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013426 okc_enable = TRUE;
13427 sae_MFP = TRUE;
13428 sae_pwe = 2;
13429 disable_EAPOL_retries = FALSE;
13430 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013431 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013432 sae_MFP = TRUE;
13433 sae_pwe = 2;
13434 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013435 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013436 strcpy(wpa_mode, "OWE");
13437 sae_MFP = TRUE;
13438 sae_pwe = 2;
13439 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013440 }
13441
13442 band = wifi_index_to_band(ap_index);
13443 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13444 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13445 return RETURN_ERR;
13446 }
developer587c1b62022-09-27 15:58:59 +080013447
13448 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013449 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013450 wifi_setSAEMFP(ap_index, sae_MFP);
13451 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013452 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013453
developerae432c62023-04-24 11:07:20 +080013454 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013455 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) {
13456 int key_len = strlen(security->u.key.key);
13457 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13458 if (key_len == 64) { // set wpa_psk
13459 strncpy(password, security->u.key.key, 64); // 64 characters
13460 password[64] = '\0';
13461 wifi_setApSecurityPreSharedKey(ap_index, password);
13462 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13463 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13464 strncpy(password, security->u.key.key, 63);
13465 password[63] = '\0';
13466 wifi_setApSecurityKeyPassphrase(ap_index, password);
13467 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13468 } else
13469 return RETURN_ERR;
13470 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013471 }
13472 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13473 params.name = "sae_password";
13474 params.value = security->u.key.key;
13475 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013476 } else { // remove sae_password
13477 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13478 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013479 }
13480 }
developer587c1b62022-09-27 15:58:59 +080013481
13482 if (security->mode != wifi_security_mode_none) {
13483 memset(&params, 0, sizeof(params));
13484 params.name = "wpa_pairwise";
13485 if (security->encr == wifi_encryption_tkip)
13486 params.value = "TKIP";
13487 else if (security->encr == wifi_encryption_aes)
13488 params.value = "CCMP";
13489 else if (security->encr == wifi_encryption_aes_tkip)
13490 params.value = "TKIP CCMP";
13491 wifi_hostapdWrite(config_file, &params, 1);
13492 }
13493
13494 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013495 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013496 else if (security->mfp == wifi_mfp_cfg_optional)
13497 strcpy(mfp, "Optional");
13498 else if (security->mfp == wifi_mfp_cfg_required)
13499 strcpy(mfp, "Required");
13500 wifi_setApSecurityMFPConfig(ap_index, mfp);
13501
13502 memset(&params, 0, sizeof(params));
13503 params.name = "transition_disable";
13504 if (security->wpa3_transition_disable == TRUE)
13505 params.value = "0x01";
13506 else
13507 params.value = "0x00";
13508 wifi_hostapdWrite(config_file, &params, 1);
13509
13510 memset(&params, 0, sizeof(params));
13511 params.name = "wpa_group_rekey";
13512 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13513 params.value = buf;
13514 wifi_hostapdWrite(config_file, &params, 1);
13515
13516 memset(&params, 0, sizeof(params));
13517 params.name = "wpa_strict_rekey";
13518 params.value = security->strict_rekey?"1":"0";
13519 wifi_hostapdWrite(config_file, &params, 1);
13520
13521 memset(&params, 0, sizeof(params));
13522 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013523 if (security->eapol_key_retries == 0)
13524 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013525 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13526 params.value = buf;
13527 wifi_hostapdWrite(config_file, &params, 1);
13528
13529 memset(&params, 0, sizeof(params));
13530 params.name = "disable_pmksa_caching";
13531 params.value = security->disable_pmksa_caching?"1":"0";
13532 wifi_hostapdWrite(config_file, &params, 1);
13533
developer23e71282023-01-18 10:25:19 +080013534 if (multiple_set == FALSE) {
13535 wifi_setApEnable(ap_index, FALSE);
13536 wifi_setApEnable(ap_index, TRUE);
13537 }
developer587c1b62022-09-27 15:58:59 +080013538
13539 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13540
developer06a01d92022-09-07 16:32:39 +080013541 return RETURN_OK;
13542}
13543
13544INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13545{
developer9df4e652022-10-11 11:27:38 +080013546 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013547 char config_file[128] = {0};
13548 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013549 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013550
13551 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13552 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13553 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13554 security->mode = wifi_security_mode_none;
13555 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013556 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013557 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013558 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013559 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013560 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013561 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013562 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013563 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013564 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013565 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013566 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013567 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013568 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013569 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013570 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013571 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013572 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013573 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013574 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013575 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013576 }
13577
13578 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13579 if (security->mode == wifi_security_mode_none)
13580 security->encr = wifi_encryption_none;
13581 else {
13582 if (strcmp(buf, "TKIP") == 0)
13583 security->encr = wifi_encryption_tkip;
13584 else if (strcmp(buf, "CCMP") == 0)
13585 security->encr = wifi_encryption_aes;
13586 else
13587 security->encr = wifi_encryption_aes_tkip;
13588 }
13589
developer9df4e652022-10-11 11:27:38 +080013590 if (security->mode != wifi_encryption_none) {
13591 memset(buf, 0, sizeof(buf));
13592 // wpa3 can use one or both configs as password, so we check sae_password first.
13593 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013594 if (strlen(buf) != 0) {
13595 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13596 security->u.key.type = wifi_security_key_type_sae;
13597 set_sae = TRUE;
13598 strncpy(security->u.key.key, buf, sizeof(buf));
13599 }
13600 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13601 if (strlen(buf) != 0){
13602 if (set_sae == TRUE)
13603 security->u.key.type = wifi_security_key_type_psk_sae;
13604 else if (strlen(buf) == 64)
13605 security->u.key.type = wifi_security_key_type_psk;
13606 else
13607 security->u.key.type = wifi_security_key_type_pass;
13608 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013609 }
developer9df4e652022-10-11 11:27:38 +080013610 security->u.key.key[255] = '\0';
13611 }
13612
developer587c1b62022-09-27 15:58:59 +080013613 memset(buf, 0, sizeof(buf));
13614 wifi_getApSecurityMFPConfig(ap_index, buf);
13615 if (strcmp(buf, "Disabled") == 0)
13616 security->mfp = wifi_mfp_cfg_disabled;
13617 else if (strcmp(buf, "Optional") == 0)
13618 security->mfp = wifi_mfp_cfg_optional;
13619 else if (strcmp(buf, "Required") == 0)
13620 security->mfp = wifi_mfp_cfg_required;
13621
13622 memset(buf, 0, sizeof(buf));
13623 security->wpa3_transition_disable = FALSE;
13624 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13625 disable = strtol(buf, NULL, 16);
13626 if (disable != 0)
13627 security->wpa3_transition_disable = TRUE;
13628
13629 memset(buf, 0, sizeof(buf));
13630 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13631 if (strlen(buf) == 0)
13632 security->rekey_interval = 86400;
13633 else
13634 security->rekey_interval = strtol(buf, NULL, 10);
13635
13636 memset(buf, 0, sizeof(buf));
13637 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13638 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013639 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013640 else
13641 security->strict_rekey = strtol(buf, NULL, 10);
13642
13643 memset(buf, 0, sizeof(buf));
13644 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13645 if (strlen(buf) == 0)
13646 security->eapol_key_retries = 4;
13647 else
13648 security->eapol_key_retries = strtol(buf, NULL, 10);
13649
13650 memset(buf, 0, sizeof(buf));
13651 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13652 if (strlen(buf) == 0)
13653 security->disable_pmksa_caching = FALSE;
13654 else
13655 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13656
13657 /* TODO
13658 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13659 */
13660 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13661 security->eap_identity_req_timeout = 0;
13662 security->eap_identity_req_retries = 0;
13663 security->eap_req_timeout = 0;
13664 security->eap_req_retries = 0;
13665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013666 return RETURN_OK;
13667}
13668
13669#endif /* WIFI_HAL_VERSION_3 */
13670
13671#ifdef WIFI_HAL_VERSION_3_PHASE2
13672INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13673{
developerd946fd62022-12-08 18:03:28 +080013674 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013675 char cmd[128] = {0};
13676 char buf[128] = {0};
13677 char *mac_addr = NULL;
13678 BOOL status = FALSE;
13679 size_t len = 0;
13680
13681 if(ap_index > MAX_APS)
13682 return RETURN_ERR;
13683
13684 *output_numDevices = 0;
13685 wifi_getApEnable(ap_index, &status);
13686 if (status == FALSE)
13687 return RETURN_OK;
13688
developerac6f1142022-12-20 19:26:35 +080013689 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013690 return RETURN_ERR;
13691 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013692 _syscmd(cmd, buf, sizeof(buf));
13693
13694 mac_addr = strtok(buf, "\n");
13695 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13696 *output_numDevices = i + 1;
13697 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13698 addr_ptr = output_deviceMacAddressArray[i];
13699 mac_addr_aton(addr_ptr, mac_addr);
13700 mac_addr = strtok(NULL, "\n");
13701 }
13702
13703 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013704}
13705#else
13706INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13707{
developerd946fd62022-12-08 18:03:28 +080013708 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013709 char cmd[128];
13710 BOOL status = false;
13711
13712 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13713 return RETURN_ERR;
13714
13715 output_buf[0] = '\0';
13716
13717 wifi_getApEnable(ap_index,&status);
13718 if (!status)
13719 return RETURN_OK;
13720
developerac6f1142022-12-20 19:26:35 +080013721 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013722 return RETURN_ERR;
13723 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013724 _syscmd(cmd, output_buf, output_buf_size);
13725
13726 return RETURN_OK;
13727}
13728#endif
developer2f513ab2022-09-13 14:26:06 +080013729
13730INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13731{
13732 char output[16]={'\0'};
13733 char config_file[MAX_BUF_SIZE] = {0};
13734
13735 if (!enable)
13736 return RETURN_ERR;
13737
13738 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13739 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13740
13741 if (strlen(output) == 0)
13742 *enable = FALSE;
13743 else if (strncmp(output, "1", 1) == 0)
13744 *enable = TRUE;
13745 else
13746 *enable = FALSE;
13747
13748 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13749 return RETURN_OK;
13750}
developer2d9c30f2022-09-13 15:06:14 +080013751
13752INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13753{
developer804c64f2022-10-19 13:54:40 +080013754 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013755 return RETURN_ERR;
13756 *output_enable=TRUE;
13757 return RETURN_OK;
13758}
developerfd7d2892022-09-13 16:44:53 +080013759
13760INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13761{
13762 char cmd[128] = {0};
13763 char buf[128] = {0};
13764 char line[128] = {0};
13765 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013766 FILE *f = NULL;
13767 int index = 0;
13768 int exp = 0;
13769 int mantissa = 0;
13770 int duration = 0;
13771 int radio_index = 0;
13772 int max_radio_num = 0;
13773 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013774 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013775 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13776
13777 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013778
developerfd7d2892022-09-13 16:44:53 +080013779 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013780
13781 phyId = radio_index_to_phy(radio_index);
13782 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013783 _syscmd(cmd, buf, sizeof(buf));
13784 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13785 if (*numSessionReturned > maxNumberSessions)
13786 *numSessionReturned = maxNumberSessions;
13787 else if (*numSessionReturned < 1) {
13788 *numSessionReturned = 0;
13789 return RETURN_OK;
13790 }
13791
developer033b37b2022-10-18 11:27:46 +080013792 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 +080013793 if ((f = popen(cmd, "r")) == NULL) {
13794 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13795 return RETURN_ERR;
13796 }
13797
13798 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013799 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013800 char *tmp = NULL;
13801 strcpy(buf, line);
13802 tmp = strtok(buf, " ");
13803 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13804 tmp = strtok(NULL, " ");
13805 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13806 tmp = strtok(NULL, " ");
13807 if (strstr(tmp, "t")) {
13808 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13809 }
13810 if (strstr(tmp, "a")) {
13811 twtSessions[index].twtParameters.operation.announced = TRUE;
13812 }
13813 tmp = strtok(NULL, " ");
13814 exp = strtol(tmp, NULL, 10);
13815 tmp = strtok(NULL, " ");
13816 mantissa = strtol(tmp, NULL, 10);
13817 tmp = strtok(NULL, " ");
13818 duration = strtol(tmp, NULL, 10);
13819
13820 // only implicit supported
13821 twtSessions[index].twtParameters.operation.implicit = TRUE;
13822 // only individual agreement supported
13823 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13824
13825 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13826 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013827 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013828 // Overflow handling
13829 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13830 } else {
13831 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13832 }
13833 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13834 index++;
13835 }
13836
13837 pclose(f);
13838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13839 return RETURN_OK;
13840}